title: How to get Spring Security to respond to Pre-Flight CORS request with OAUTH2
body: <p>I am not a Java programmer by profession. I am working on building an app for our lab. It started out as a Spring MVC app with JSP files. It has now migrated to a Spring REST API that uses OAUTH2 as a standalone authentication and authorization server. I am using a MySQL database to store my data and users. I can successfully get an access_token issued if I use Postman to access the server. However if I use the Angular 2 client I setup I cannot get past the pre-flight OPTIONS request sent by the client to the server. I have tried several different ways to configure a CORS filter, but I cannot get that filter to get implemented and I always get a 401 code returned for the pre-flight request. I have tried implementing the suggested solution in the Spring blog <a href="https://spring.io/blog/2015/06/08/cors-support-in-spring-framework" rel="nofollow">https://spring.io/blog/2015/06/08/cors-support-in-spring-framework</a> but that hasn't worked yet.</p>
  
  <p>In my pom.xml file I am using these versions of Spring</p>
  
  <pre><code>Spring Framework - 4.3.2.RELEASE
  Spring Security  - 4.1.2.RELEASE
  Spring Security OAUTH2 - 2.0.10.RELEASE
  </code></pre>
  
  <p>I also included Spring Boot 1.4.0 when trying to use FilterRegistrationBean</p>
  
  <p>Here is my code as it is right now.</p>
  
  <pre><code>WebConfig Class:
  @EnableWebMvc
  @Configuration
  @ComponentScan(basePackages={"eng.lab"})
  @Import({ApplicationContext.class})
  @PropertySource("classpath:application.properties")
  public class WebConfig extends WebMvcConfigurerAdapter{
  
  /*  @Override
      public void addCorsMappings(CorsRegistry registry) {
          registry.addMapping("/**");
      }*/
  
  }
  </code></pre>
  
  <p>SecurityConfig Class:</p>
  
  <pre><code>@Configuration
  @EnableWebSecurity
  @PropertySource("classpath:application.properties")
  public class SecurityConfig extends WebSecurityConfigurerAdapter {
  
      @Autowired
      DataSource dataSource;
  
  
       @Autowired
       public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
         auth.jdbcAuthentication().dataSource(dataSource)
        .usersByUsernameQuery(
         "select username,password, enabled from user where username=?")
        .authoritiesByUsernameQuery(
         "select u.username, r.role from User u, Role r where r.id=u.roleId and u.userName=?");
       }  
  
  
       @Autowired
       private ClientDetailsService clientDetailsService;
  
  
              @Override
              protected void configure(HttpSecurity http) throws Exception {
                  http
                  .csrf().disable()
                  .anonymous().disable()
                  .authorizeRequests()
                  .antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll()
                  //.requestMatchers(CorsUtils::isCorsRequest).permitAll()
                  .antMatchers("/oauth/token").permitAll();
             }
  
              @Override
              @Bean
              public AuthenticationManager authenticationManagerBean() throws Exception {
                  return super.authenticationManagerBean();
              }
  
  
              @Bean
              public TokenStore tokenStore() {
                  return new InMemoryTokenStore();
              }
  
              @Bean
              @Autowired
              public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){
                  TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
                  handler.setTokenStore(tokenStore);
                  handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
                  handler.setClientDetailsService(clientDetailsService);
                  return handler;
              }
  
              @Bean
              @Autowired
              public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
                  TokenApprovalStore store = new TokenApprovalStore();
                  store.setTokenStore(tokenStore);
                  return store;
              }
  
          }
  </code></pre>
  
  <p>MethodSecurityConfig Class:</p>
  
  <pre><code>@Configuration
  @EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
  public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
  
      @SuppressWarnings("unused")
      @Autowired
      private SecurityConfig securityConfig;
  
      @Override
      protected MethodSecurityExpressionHandler createExpressionHandler() {
          return new OAuth2MethodSecurityExpressionHandler();
      }
  }
  </code></pre>
  
  <p>WebAppInitializer Class:</p>
  
  <pre><code>public class WebAppInitializer implements WebApplicationInitializer{
  
      @Override
      public void onStartup(ServletContext container) throws ServletException {
  
          AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
          rootContext.register(WebConfig.class);
  
          container.addListener(new ContextLoaderListener(rootContext));
  
          DelegatingFilterProxy filter = new DelegatingFilterProxy("springSecurityFilterChain");
  
          DispatcherServlet dispatcherServlet = new DispatcherServlet(rootContext);
  
          ServletRegistration.Dynamic registration = container.addServlet("dispatcherServlet", dispatcherServlet);
  
          container.addFilter("springSecurityFilterChain", filter).addMappingForUrlPatterns(null,  false, "/*");
  
          registration.setLoadOnStartup(1);
          registration.addMapping("/");
  
      }
  }
  </code></pre>
  
  <p>SimpleCorsFilter Class:</p>
  
  <pre><code>@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() {
      }
  }
  </code></pre>
  
  <p>If I include a second WebSecurityConfig class I do get a 403 code instead.</p>
  
  <p>MyWebSecurity Class:</p>
  
  <pre><code>@Configuration
  @EnableWebSecurity
  @Order(-1)
  public class MyWebSecurity extends WebSecurityConfigurerAdapter {
     @Override
     protected void configure(HttpSecurity http) throws Exception {
         http
            .authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll();
     }
  }
  </code></pre>
  
  <p>Any suggestions as to how to get past the pre-flight issue beyond waiting for the DATAREST-573 bug to be fixed?  </p>
  
  <p>UPDATE:  I tried Benjamin's suggestion, but not sure I implemented the solution properly. I have edited my WebConfig class as folows but the pre-flight still fails. The filter still isn't getting applied.</p>
  
  <pre><code>package eng.lab.config;
  
  
  import javax.servlet.Filter;
  
  import org.springframework.boot.web.servlet.FilterRegistrationBean;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.ComponentScan;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.context.annotation.Import;
  import org.springframework.context.annotation.PropertySource;
  import org.springframework.web.servlet.config.annotation.EnableWebMvc;
  import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  
  @EnableWebMvc
  @Configuration
  @ComponentScan(basePackages={"eng.lab"})
  @Import({ApplicationContext.class})
  @PropertySource("classpath:application.properties")
  public class WebConfig extends WebMvcConfigurerAdapter{
  
      //more custome rule beans
  
      @Bean
      public FilterRegistrationBean simpleCORSFilterRegistration() {
  
          FilterRegistrationBean registration = new FilterRegistrationBean();
          registration.setFilter(new SimpleCorsFilter());
          registration.addUrlPatterns("/*");
          //registration.addInitParameter("paramName", "paramValue");
          registration.setName("simpleCorsFilter");
          registration.setOrder(0);
          return registration;
      } 
  
      @Bean(name = "simpleCorsFilter")
      public Filter simpleCorsFilter() {
          return new SimpleCorsFilter();
      }
  
  /*  @Override
      public void addCorsMappings(CorsRegistry registry) {
          registry.addMapping("/**");
      }*/
  
  }
  </code></pre>