Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring security OAuth2 authentication and form login in one app

Is it possible to combine authoryzation and authentication by login basic and by oauth2 in one application?

My project is based on jhipster project with simple spring security session login, now i need add oauth2 security for mobile app and it's look like it is not possible.

Now i have situation when work one of them, oauth2 ok if WebSecurityConfigurerAdapter had bigger order number than ResourceServerConfiguration. That's mean if oauth security filter is first. I read a lot in stackoverflow and try many solution like: Spring security oauth2 and form login configuration for me thats one don't work.
Now i know that is related with some security filter conflict but i dont know how to fix it.

if someone had a similar problem and he managed to do it, or know how to get around or make it better I will be grateful for the information. Thanks in advance for your help :)

@Configuration
@EnableWebSecurity
public class SecurityOauth2Configuration extends WebSecurityConfigurerAdapter {

  @Inject
  private UserDetailsService userDetailsService;

  @Override
  @Bean
  public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth
        .userDetailsService(userDetailsService)
        .passwordEncoder(passwordEncoder());
}

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring()
        .antMatchers("/scripts/**/*.{js,html}")
        .antMatchers("/bower_components/**")
        .antMatchers("/i18n/**")
        .antMatchers("/assets/**")
        .antMatchers("/swagger-ui/index.html")
        .antMatchers("/api/register")
        .antMatchers("/api/activate")
        .antMatchers("/api/account/reset_password/init")
        .antMatchers("/api/account/reset_password/finish")
        .antMatchers("/test/**");
}


@Configuration
@EnableAuthorizationServer
public static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    private static final String OAUTH_SECURITY = "jhipster.security.authentication.oauth.";
    private static final String CLIENTID = "clientid";
    private static final String SECRET = "secret";
    private static final String TOKEN_VALIDATION_TIME = "tokenValidityInSeconds";

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.tokenKeyAccess("isAnonymous() || hasAuthority('"+AuthoritiesConstants.USER+"')").checkTokenAccess("hasAuthority('"+AuthoritiesConstants.USER+"')");
    }
    @Inject
    private Environment env;
    @Inject
    private DataSource dataSource;

    @Bean
    public TokenStore tokenStore() {
        return new JdbcTokenStore(dataSource);
    }
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
            .authenticationManager(authenticationManager)
            .tokenStore(tokenStore())
        ;
    }




    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
            .inMemory()
            .withClient(env.getProperty(OAUTH_SECURITY + CLIENTID))
            .scopes("read", "write")
            .authorities(AuthoritiesConstants.ADMIN, AuthoritiesConstants.USER)
            .authorizedGrantTypes("password", "refresh_token")
            .secret(env.getProperty(OAUTH_SECURITY + SECRET))
            .accessTokenValiditySeconds(env.getProperty(OAUTH_SECURITY + TOKEN_VALIDATION_TIME, Integer.class, 18000));

    }
}


@Configuration
@Order(1)
public static class SecurityWebConfiguration extends WebSecurityConfigurerAdapter {
    @Inject
    private Environment env;

    @Inject
    private AjaxAuthenticationSuccessHandler ajaxAuthenticationSuccessHandler;

    @Inject
    private AjaxAuthenticationFailureHandler ajaxAuthenticationFailureHandler;

    @Inject
    private AjaxLogoutOauthSuccessHandler ajaxLogoutSuccessHandler;

    @Inject
    private RememberMeServices rememberMeServices;


    @Override
    protected void configure(HttpSecurity http) throws Exception {


        http
                .csrf().disable().authorizeRequests()
            .and()
                .formLogin()
                .loginProcessingUrl("/api/authentication")
                .successHandler(ajaxAuthenticationSuccessHandler)
                .failureHandler(ajaxAuthenticationFailureHandler)
                .usernameParameter("j_username")
                .passwordParameter("j_password")
                .permitAll()
            .and()
                .rememberMe()
            .rememberMeServices(rememberMeServices)
                .key(env.getProperty("jhipster.security.rememberme.key"))
            .and()
                .logout()
            .logoutUrl("/api/logout")
            .logoutSuccessHandler(ajaxLogoutSuccessHandler)
            .deleteCookies("JSESSIONID")
                .permitAll()
            .and()
                .exceptionHandling()
        ;



    }

}


@Order(2)
@Configuration
@EnableResourceServer
public static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    @Inject
    private Http401UnauthorizedEntryPoint authenticationEntryPoint;

    @Inject
    private AjaxLogoutOauthSuccessHandler ajaxLogoutSuccessHandler;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        ContentNegotiationStrategy contentNegotiationStrategy = http.getSharedObject(ContentNegotiationStrategy.class);
        if (contentNegotiationStrategy == null) {
            contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
        }
        MediaTypeRequestMatcher preferredMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy,
            MediaType.APPLICATION_FORM_URLENCODED,
            MediaType.APPLICATION_JSON,
            MediaType.MULTIPART_FORM_DATA);


        http
            .authorizeRequests()
            .and()
                .anonymous()
            .disable()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
                .httpBasic()
            .and()
                .exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint)
                .defaultAuthenticationEntryPointFor(authenticationEntryPoint, preferredMatcher)
            .and()
                .authorizeRequests()
                .antMatchers("/api/**").fullyAuthenticated();


    }
}

}

For this settings WebSecurityConfigurerAdapter session work correctly. For OAuth after correctly authorizatization i get valid acces token, but for request with this token from session i get this result:

  public static String getCurrentLogin() {
    SecurityContext securityContext = SecurityContextHolder.getContext();
    Authentication authentication = securityContext.getAuthentication();


    UserDetails springSecurityUser = null;
    String userName = null;
    if(authentication != null) {
        if (authentication.getPrincipal() instanceof UserDetails) {
            springSecurityUser = (UserDetails) authentication.getPrincipal();
            userName = springSecurityUser.getUsername();
        } else if (authentication.getPrincipal() instanceof String) {
            userName = (String) authentication.getPrincipal();
        }
    }
    System.out.println(userName);                          // show anonymousUser
    System.out.println(authentication.isAuthenticated());  //show true
    System.out.println(authentication.getAuthorities());   //show [ROLE_ANONYMOUS]
    System.out.println(userName);                          //show anonymousUser

    return userName;
}

function write in console: anonymousUser true [ROLE_ANONYMOUS] anonymousUser

and should be user1 true [ROLE_USER] user1

like image 725
Wojciech Avatar asked Oct 25 '15 02:10

Wojciech


1 Answers

The apps git urls: https://github.com/rynkowsw/oauth2 it is oauth2 app https://github.com/rynkowsw/web-and-oauth2-security this is web and oauth2 security app

This app are adapted from jhipster.github.io

to run app you need have postgres db in localhost, like in db resource file:

    driver-class-name: org.postgresql.ds.PGSimpleDataSource
    url: jdbc:postgresql://localhost:5432/gymapp
    name: gymapp
    serverName: localhost:5432
    username: postgres
    password: jaja

To test app the fastest way is:

 http://localhost:8080/oauth/token
 headers:  Authorization: Basic amhpcHN0ZXJhcHA6bXlTZWNyZXRPQXV0aFNlY3JldA==

this string after basic is combination default jhispter oauth secret and clientid base64 encrypt result

then

  http://localhost:8080/api/account
  headers:  Authorization: bearer [token from response in first request]

For this same db, result for oauth are: for oauth2 app

{
 login: "user"
 password: null
 firstName: "User"
 lastName: "User"
 email: "user@localhost"
 activated: true
 langKey: "en"
 authorities: [1]
 0:  "ROLE_USER"
 -
}

for web + oauth2 security:

 {
  login: "anonymousUser"
  password: null
  firstName: "Anonymous"
  lastName: "User"
  email: "anonymous@localhost"
  activated: true
  langKey: "en"
  authorities: [0]
  }
like image 190
Wojciech Avatar answered Oct 19 '22 23:10

Wojciech