Standalone Spring OAuth2 JWT Authorization Server + CORS

无人久伴 提交于 2019-11-26 21:41:20
Michael K.

Found the reason for my Problem!

I just needed to end the filterchain and return the result immediatly if a OPTIONS request is processed by the CorsFilter!

SimpleCorsFilter.java

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCorsFilter implements Filter {

    public SimpleCorsFilter() {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization");

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, res);
        }
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {
    }
}

After that I could ignore the OPTIONS preflight request in my AuthServer =D

So the Server works as in the snipped above and you can ignore the block comment with MyWebSecurity class in the beginning.

I found a solution using the solution for the question. But I have another way to describe the solution:

@Configuration
public class WebSecurityGlobalConfig extends WebSecurityConfigurerAdapter {
      ....
      @Override
      public void configure(WebSecurity web) throws Exception {
        web.ignoring()
          .antMatchers(HttpMethod.OPTIONS);
      }
      ...
}

I came across similar issue using following

  • Backend Spring Boot 1.5.8.RELEASE
  • Spring OAuth2 Spring OAuth 2.2.0.RELEASE w
  • Vuejs app using axios ajax request library

With postman everything works! When I started making request from Vuejs app then I got the following errors

OPTIONS http://localhost:8080/springboot/oauth/token 401 ()

and

XMLHttpRequest cannot load http://localhost:8080/springboot/oauth/token. Response for preflight has invalid HTTP status code 401

After reading a bit, I found out that I can instruct my Spring OAuth to ignore the OPTIONS request by overriding configure in my WebSecurityConfigurerAdapter implementation class as follow

@Override
public void configure(WebSecurity web) throws Exception {
   web.ignoring().antMatchers(HttpMethod.OPTIONS);
}

Addition of the above helped but then, I came across the CORS specific error

OPTIONS http://localhost:8080/springboot/oauth/token 403 ()

and

XMLHttpRequest cannot load http://localhost:8080/springboot/oauth/token. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access. The response had HTTP status code 403.

And solved the above issue with the help of a CorsConfig as shown below

@Configuration
public class CorsConfig {
    @Bean
    public FilterRegistrationBean corsFilterRegistrationBean() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.applyPermitDefaultValues();
        config.setAllowCredentials(true);
        config.setAllowedOrigins(Arrays.asList("*"));
        config.setAllowedHeaders(Arrays.asList("*"));
        config.setAllowedMethods(Arrays.asList("*"));
        config.setExposedHeaders(Arrays.asList("content-length"));
        config.setMaxAge(3600L);
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
}

After addition of the above class, it works as expected. Before I go prod I will research consequences of using

web.ignoring().antMatchers(HttpMethod.OPTIONS);

as well as best practices for above Cors configuration. For now * does the job but, definitely not secure for production.

Cyril's answer helped me partially and then I came across the CorsConfig idea in this Github issue.

well, you're right! that's a solution, and it worked also for me (I had the same issue)

But let me sussgest to use a smarter CORS Filter implementation for Java: http://software.dzhuvinov.com/cors-filter.html

This is very complete solution for Java applications.

Actually, you can see here how your point is resolved.

Using Spring Boot 2 here.

I had to do this in my AuthorizationServerConfigurerAdapter

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {

    Map<String, CorsConfiguration> corsConfigMap = new HashMap<>();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    //TODO: Make configurable
    config.setAllowedOrigins(Collections.singletonList("*"));
    config.setAllowedMethods(Collections.singletonList("*"));
    config.setAllowedHeaders(Collections.singletonList("*"));
    corsConfigMap.put("/oauth/token", config);
    endpoints.getFrameworkEndpointHandlerMapping()
            .setCorsConfigurations(corsConfigMap);

    //additional settings...
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!