22

I am using spring security oauth in my project. I am excluding some urls from authentication by configuring in spring security ResourceServerConfigurerAdapter. I added http.authorizeRequests().antMatchers(url).permitAll().

Now, what I am seeing is that, if I don't pass the Authorization header to these urls, it is not authenticated. And the API is called properly.

If the call is made with an Authorization header, then it validates the token and fails the call if the token is not validated.

My question is what do I need to do so that the token is ignored in the request for which I have permitAll.

user3565529
  • 1,317
  • 2
  • 14
  • 24

4 Answers4

8

Spring OAuth2 will intercept all url with header: Authorization Bearer xxx.

To avoid Spring OAuth2 from intercept the url. I have created a SecurityConfiguration which has higher order than Spring OAuth2 configuration.

@Configuration
@EnableWebSecurity
@Order(1) // this is important to run this before Spring OAuth2 
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        List<RequestMatcher> requestMatchers = new ArrayList<RequestMatcher>();
        // allow /api/public/product/** and /api/public/content/** not intercepted by Spring OAuth2
        requestMatchers.add(new AntPathRequestMatcher("/api/public/product/**"));
        requestMatchers.add(new AntPathRequestMatcher("/api/public/content/**"));

    http
        .requestMatcher(new OrRequestMatcher(requestMatchers))
    .authorizeRequests()
      .antMatchers("/api/public/product/**", "/api/public/content/**").permitAll()
    }
}

The above configuration allows /api/public/product/** and /api/public/content/** to be handled by this configuration, not by Spring OAuth2 because this configuration has higher @Order.

Therefore, even setting invalid token to above api call will not result in invalid access token.

SooCheng Koh
  • 2,271
  • 3
  • 21
  • 34
  • 1
    But if token is valid you can not get the authenticated user. – meobeo173 Dec 18 '17 at 06:48
  • @meobeo173 Yes, as u said, I can't get userInfo from auth-server. So, I switch `user-info-url` endpoint to api-server. – Cataclysm Jan 11 '18 at 05:50
  • @meobeo173 I'm using `spring-oauth2` with `spring-boot` setup. But I created url to fetch authenticated user informations (`security.oauth2.resource.user-info-uri`) at my auth-server. It is ok before I change my spring-security configurations class's order to `1` as this answer described. So, I moved `user-info-uri` end-point to my `api-server` that serves rest-services from `auth-server` application . – Cataclysm Jan 11 '18 at 08:31
4

As per spring-oauth2 docs https://projects.spring.io/spring-security-oauth/docs/oauth2.html

Note: if your Authorization Server is also a Resource Server then there is another security filter chain with lower priority controlling the API resources. Fo those requests to be protected by access tokens you need their paths not to be matched by the ones in the main user-facing filter chain, so be sure to include a request matcher that picks out only non-API resources in the WebSecurityConfigurer above.

So define WebSecurityConfigurer implementation with higher order than ResourceServerConfig.

hemantvsn
  • 1,316
  • 3
  • 12
  • 24
  • 1
    Can you explain the text in bold a little in detail? I mean, if there is another security filter chain with lower priority, why does it get to control the API resources? And if we maintain a WebSecurityConfigurer for the non-API resources, what are these non-api resources? @hermantvsn – sbsatter Jul 24 '19 at 08:46
0

In case you are dealing with Reactive Spring webflux, from SooCheng Koh's answer.

@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
@Order(1) // this is important to run this before Spring OAuth2
public class PublicSecurityConfiguration {


    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {

        http

            .authorizeExchange()
            .pathMatchers("/api/public/**").permitAll();
        return http.build();
    }
}
Maxx
  • 421
  • 5
  • 9
0

It's not a bug it's a feature :)

As already mentioned by other people, even if you have permitAll, Spring Security will still check the token if there is a header "Authorization". I don't like the workaround on the backend with Order(1) so I did a change on the frontend simply removing the header "Authorization" for the specific request. Angular example with interceptor:

@Injectable()
export class PermitAllInterceptor implements HttpInterceptor {
  constructor() {}
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if(req.url.includes('permitAllUrl')){
      req = req.clone({ headers: req.headers.delete('Authorization') });
    }
    return next.handle(req);
  }
}

and then just register the interceptor in app.module.ts:

{
  provide: HTTP_INTERCEPTORS,
  useClass: PermitAllInterceptor ,
  multi: true
}
NikNik
  • 2,191
  • 2
  • 15
  • 34