Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configuring spring security using oAuth and form based authentication

I have a server application with two components: a) A set of REST API that are secured using oAuth ( Spring security oAuth) b) A dashboard for management with role based UI

For business reasons, these two components need to be co-hosted i.e deployed as a single war. Till now we only had oAuth for our REST API's and all was well. The problem started when we tried to use form based authentication for the dashboard. Now, when we access REST API's without an oAuth token, it just redirects to the login page instead of giving a 401 unauthorized error. Our configuration is like this: Form based authentication(WebSecurityConfigurerAdapter):

 http
        .csrf().disable()
        .authorizeRequests()
         .antMatchers("/css/**","/img/**","/login/**","/oauth/**).permitAll()
                 .anyRequest().authenticated()
             .and()
            .formLogin().loginPage("/login")
          .defaultSuccessUrl("/delegate/success", true)
            .failureUrl("/login/fail")
                .permitAll()
           .and()
        .logout()
            .logoutUrl("/logout")
            .logoutSuccessUrl("/login")                                  
            .permitAll();

oAuth:

Resource provider configuration:

    http
            .authorizeRequests()
                .antMatchers("/abc").access("#oauth2.hasScope('read')and hasRole('ROLE_USER')")
                .antMatchers("/xyz").access("#oauth2.hasScope('read') and hasRole('ROLE_ADMIN')")

We would basically like to configure different API to be secured differently. REST API consumed by client applications have to be secured by oAuth and Spring MVC API rendering dashboard pages with form based authentication. Is this even possible?

EDIT: Add ordering and able to get 401 unauthorized message on accessing oauth protected REST APIs. Form login doesnt work though. I am able to access all dashboard pages without login. More code snippets:

 @Configuration
    @EnableResourceServer
    public class ResourceProviderConfiguration extends   ResourceServerConfigurerAdapter {
    .....
    @Override
    public void configure(HttpSecurity http) throws Exception {
    http
                .authorizeRequests()
                    .antMatchers("/abc").access("#oauth2.hasScope('read')and  hasRole('ROLE_USER')")
                    .antMatchers("/xyz").access("#oauth2.hasScope('read') and  hasRole('ROLE_ADMIN')").
.and()
                    .requestMatchers()
                    .antMatchers("/abc","/xyz","/others");

       }

    }
    @Configuration
    @EnableAuthorizationServer
    public class AuthorizationProviderConfiguration extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private UserApprovalHandler userApprovalHandler;

    @Autowired
    ClientDetailsService webClientDetailsService;


    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;

    .......
    @Bean
    public TokenStore tokenStore() {
        return new InMemoryTokenStore();
    }
    ......
    }

    @Configuration
    @EnableWebSecurity
    @Order(5)
    public class UserAuthenticationConfiguration extends     WebSecurityConfigurerAdapter {

     @Override
     protected void configure(HttpSecurity http) throws Exception {
      http
            .csrf().disable()
            .authorizeRequests()                              
            .antMatchers("/css/**","/img/**","/login/**",
             "/oauth/**).permitAll()
                     .anyRequest().authenticated()
                 .and()
                .formLogin().loginPage("/login")
              .defaultSuccessUrl("/delegate/success", true)
                .failureUrl("/login/fail")
                    .permitAll()
               .and()
            .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login")                                  
                .permitAll();

    }
    }

Spring security logs:

DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant    [pattern='/oauth/token']
DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/def'; against '/oauth/token'
DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/oauth/token_key']
DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/def'; against '/oauth/token_key'
DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/oauth/check_token']
DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/def'; against '/oauth/check_token'
DEBUG o.s.s.w.u.matcher.OrRequestMatcher - No matches found
DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/abc/**']
DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/def'; against '/abc/**'
DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/xyz/**']
DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/def'; against '/xyz/**'
DEBUG o.s.s.w.u.matcher.OrRequestMatcher - No matches found
DEBUG o.s.security.web.FilterChainProxy - '/def' at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
DEBUG o.s.security.web.FilterChainProxy - '/def' at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@7f8059. A new one will be created.
DEBUG o.s.security.web.FilterChainProxy - '/def' at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
DEBUG o.s.s.w.h.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@cebda04
DEBUG o.s.security.web.FilterChainProxy - '/def' at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter'
DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/def'; against '/logout'
DEBUG o.s.security.web.FilterChainProxy - '/def' at position 5 of 11 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET '/def'' doesn't match 'POST /login/new
DEBUG o.s.security.web.FilterChainProxy - '/def' at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
DEBUG o.s.security.web.FilterChainProxy - '/def' at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
DEBUG o.s.security.web.FilterChainProxy - '/def' at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@905571d8: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: 127.0.0.1; SessionId: 794828541EF505314237BBC81C2ACAF4; Granted Authorities: ROLE_ANONYMOUS'
DEBUG o.s.security.web.FilterChainProxy - '/def' at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
DEBUG o.s.security.web.FilterChainProxy - '/def' at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
DEBUG o.s.security.web.FilterChainProxy - '/def' at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/def'; against '/css/**'
DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/def'; against '/oauth/**'
DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/def'; against '/img/**'
DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/def'; against '/login/**'
DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Public object - authentication not attempted
DEBUG o.s.security.web.FilterChainProxy - '/def' reached end of additional     filter chain; proceeding with original chain
DEBUG o.s.web.servlet.DispatcherServlet - DispatcherServlet with name 'webservice' processing GET request for ['/handler/def']

Final Configuration that worked: 1. Adding @Order to the web security configurer, after the resource provider configuration which defaults to 3.

  1. Ensuring that WebSecurityConfigurerAdapter has .anyRequest().authenticated() config

    @Configuration
    @EnableResourceServer
    public class ResourceProviderConfiguration extends   ResourceServerConfigurerAdapter {
    .....
    @Override
    public void configure(HttpSecurity http) throws Exception {
    http
                .authorizeRequests()
                    .antMatchers("/abc").access("#oauth2.hasScope('read')and   hasRole('ROLE_USER')")
                    .antMatchers("/xyz").access("#oauth2.hasScope('read')   and  hasRole('ROLE_ADMIN')").
                    .and()
                    .requestMatchers()
                    .antMatchers("/abc","/xyz","/others");
    
       }
    
    }
    @Configuration
    @EnableAuthorizationServer
    public class AuthorizationProviderConfiguration extends AuthorizationServerConfigurerAdapter {
    
    @Autowired
    private TokenStore tokenStore;
    
    @Autowired
    private UserApprovalHandler userApprovalHandler;
    
    @Autowired
    ClientDetailsService webClientDetailsService;
    
    
    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;
    
    .......
    @Bean
    public TokenStore tokenStore() {
        return new InMemoryTokenStore();
    }
    ......
    }
    
    @Configuration
    @EnableWebSecurity
    @Order(5)
    public class UserAuthenticationConfiguration extends     WebSecurityConfigurerAdapter {
    
     @Override
     protected void configure(HttpSecurity http) throws Exception {
      http
            .csrf().disable()
            .authorizeRequests()                              
            .antMatchers("/css/**","/img/**","/login/**",
             "/oauth/**).permitAll()
                     .anyRequest().authenticated()
                 .and()
                .formLogin().loginPage("/login")
              .defaultSuccessUrl("/delegate/success", true)
                .failureUrl("/login/fail")
                    .permitAll()
               .and()
            .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login")                                  
                .permitAll();
    
    }
    }
    
like image 996
AVM Avatar asked Dec 14 '25 23:12

AVM


1 Answers

I can see it checking your permitAll() matchers in the logs, but there's no sign of the anyRequest().authenticated(). You need to add a request matcher to the HttpSecurity as well (i.e. http.requestMatchers().anyRequest()).

like image 52
Dave Syer Avatar answered Dec 16 '25 21:12

Dave Syer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!