Why Spring Security permitAll() is not working with OAuth2.0?

11,522

I got the issue. It was the context path which was causing the issue. I am having a dispatcher servlet defined with a mapping URL /api/v1/* and as one can see my signup request, it contains a context path i.e http://localhost:8085/api/v1/signup

For OAuth2 configuration in Spring, we need to take extra care of context path. First, it should be defined in the AuthorizationServer

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
  @Override
  public void configure(final AuthorizationServerEndpointsConfigurer endpoints) { 
        endpoints
        .prefix("/api/v1") //here
        .tokenStore(tokenStore())
        .accessTokenConverter(accessTokenConverter())
        .authenticationManager(authenticationManager)
        .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
  }

Then, the context must be added to the permitAll() path like this

@Override
public void configure(final HttpSecurity http) throws Exception {
    http
    .authorizeRequests()
    .antMatchers("/api/v1/signup").permitAll()  //context path here
    .anyRequest().authenticated();
}

Up till now, the signup request is still expected to pass a access token with it. For removing the OAuth security from signup, we need to remove security at the WebSecurity, which can be done using WebSecurityConfigurerAdapter

@EnableWebSecurity
@EnableGlobalMethodSecurity
@ComponentScan(basePackages = { "com.sample.rest.security" })
public class SecurityConfig extends WebSecurityConfigurerAdapter {

     @Override
     public void configure(WebSecurity webSecurity) throws Exception {
        webSecurity.ignoring().antMatchers("/signup");
     }
 //////////// OR use below method ///////////
/*  @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.
        authorizeRequests().antMatchers("/signup/**").permitAll();
    }
*/
}

Note, there is no use to add context path to the WebSecurityConfigurerAdapter configuration.

Share:
11,522
The Coder
Author by

The Coder

A self-taught developer interested in all technical stuffs.

Updated on June 11, 2022

Comments

  • The Coder
    The Coder almost 2 years

    I have a REST API secured with OAuth2.0 I am able to get the access-token using http://localhost:8085/auth/token?grant_type=password&[email protected]&password=mypass(along with username pass basic auth).
    But when I am trying to access http://localhost:8085/api/v1/signup , API returns a 401 unauthorized error.
    Though I have used antMatchers("/signup").permitAll(), why API is expecting a access-token to access this resource? Passing access-token along with this request would signup a user.
    This is my resource server configuration

    @Configuration
    @EnableResourceServer
    public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    
    //require beans and methods here
    
    @Autowired
    public void configureGlobal(final AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(authProvider());
    }
    
    @Override
    public void configure(final HttpSecurity http) throws Exception {
        http
        .authorizeRequests()
        .antMatchers("/signup").permitAll()
        .anyRequest().authenticated()
        .and()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
        .csrf().disable();
    }
    }
    

    Update: As suggested by this thread, I ignored /signup at ``, but that also didn't worked.

    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
    @ComponentScan(basePackages = { "com.sample.rest.security" })
    @Order(2)
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        //other Beans & methods
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            List<RequestMatcher> requestMatchers = new ArrayList<RequestMatcher>();
            requestMatchers.add(new AntPathRequestMatcher("/signup/**"));
    
            http.
            requestMatcher(new OrRequestMatcher(requestMatchers)).
            authorizeRequests().antMatchers("/signup/**")
            .permitAll();
        }
    
    }
    
  • The Coder
    The Coder over 5 years
    Not helpful. Still same 401 unauthorized error. And btw, /signup* is used to match paths like /signup?xyz&abc=1 and /signup/** will match /signup/user kind of paths
  • idipous
    idipous about 4 years
    I had a similar problem without the context. If I was to put in the configure(HttpSecurity http) a .antMatchers("/users/**").permitAll() then GET requests worked. But any POST would require a token. It worked when I added under the configure(HttpSecurity http) your suggested configure(WebSecurity webSecurity) lines. Why is this? Do you have any pointers?
  • The Coder
    The Coder about 4 years
    @idipous I didn't get time to deeply look into what's going on. Once I get, I will update the answer.