0

I am trying to authorize all preflight request in (/secure/**) without an authorization header(oauth token in my case). The JwkFilter is used to validate the oauth token passed in the authorization header. Any suggestion, where I am going wrong here.

@Override
protected void configure(HttpSecurity http) throws Exception {
    
    JwtAuthFilter jwtAuthTokenFilter = new JwtAuthFilter(oauthConfig);
    jwtAuthTokenFilter.setAuthenticationManager(getAuthManager());

    http.cors().and().authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/secure/**")
            .permitAll();

    http.requiresChannel().anyRequest().requiresSecure().and()
            .addFilterBefore(requireProtocolFilter, ChannelProcessingFilter.class).sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().anonymous().disable().csrf().disable()
            .antMatcher("/**").authorizeRequests().anyRequest().permitAll().and()
            .antMatcher(/secure/**")
            .addFilterBefore(jwtAuthTokenFilter, BasicAuthenticationFilter.class).exceptionHandling()
            .authenticationEntryPoint(authenticationEntryPoint()).and().authorizeRequests().anyRequest()
            .authenticated();

}

public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurerAdapter() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                .allowedMethods("*")
                .allowedOrigins("*");
        }
    };
}

2 Answers2

0

For preflight request with CORS, according to spring, they will execute before your jwtAuthTokenFilter (registered before BasicAuthenticationFilter filter) -> correct

The order was specified here (in spring code):

FilterComparator() {
        Step order = new Step(INITIAL_ORDER, ORDER_STEP);
        ...
        put(CorsFilter.class, order.next());
        ...
        put(BasicAuthenticationFilter.class, order.next());
        ...
    }

In CORS, for complex request (like using custom header Authorization header in your case), browser will send preflight request first to know whether the server allow client to access their resource or not before sending actual request.

The CORSFilter will execute like this (in spring code):

public class CorsFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
            FilterChain filterChain) throws ServletException, IOException {

        CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(request);
        boolean isValid = this.processor.processRequest(corsConfiguration, request, response);
        if (!isValid || CorsUtils.isPreFlightRequest(request)) {
            return;
        }
        filterChain.doFilter(request, response);
    }
}

They will check whether for every preflight request (extends OncePerRequestFilter) comes to server, if processRequest is valid or is preflight request to terminate the chain. Here is the default processor to check preflight request (in spring code):

public class DefaultCorsProcessor implements CorsProcessor {

    @Override
    public boolean processRequest(@Nullable CorsConfiguration config, HttpServletRequest request,
            HttpServletResponse response) throws IOException {

        ...
        boolean preFlightRequest = CorsUtils.isPreFlightRequest(request);
        if (config == null) {
            if (preFlightRequest) {
                rejectRequest(new ServletServerHttpResponse(response));
                return false;
            }
            else {
                return true;
            }
        }
        return handleInternal(new ServletServerHttpRequest(request), new ServletServerHttpResponse(response), config, preFlightRequest);
    }

In your case, I think you are missing configuring for enabling CORS. So the server reject the client request (by sending HttpStatus.FORBIDDEN code), so that the browser don't send actual request to the server. And your JwtAuthTokenFilter has no chance to execute.

You can refer to this post for configuring cors. Hope it helps

Opt SD
  • 21
  • 3
  • Sorry, I did not mention I have corsConfigurer defined in the same class. I have added the code now. – Naveen Poddar Oct 16 '20 at 02:51
  • I think you also need to config CorsConfigurationSource used in CorsFilter of securityFilterChain. The corsConfigurer() here have no meaning because your request haven't reach MVC Handler. Flow: securityFilterChain -> MVC Handler. And you still stuck at securityFilterChain. – Opt SD Oct 16 '20 at 05:12
0

Adding the below snippet in to the jwkAuthFilter did the trick.

     if (CorsUtils.isPreFlightRequest(request)) {
        response.setStatus(HttpServletResponse.SC_OK);
        return;
    }