Kent Bull
Kent Bull

Reputation: 1152

CORS Filter before Authentication Filter - is less secure? Spring Security Filter Chain Order

I found that while accessing ReST services from single-page applications that in order to properly allow access to ReST endpoints I had to register a CORS filter before my authentication filter. Is this less secure or a poor security practice?

My security configuration now looks like

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

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

    @Inject
    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder.userDetailsService(userDetailsService)
                .passwordEncoder(new BCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
            .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
           .authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                .antMatchers("/health","/metrics", "/v1/users/register", "/swagger-ui/**", "/v2/api-docs").permitAll()
                .antMatchers("/mappings", "/v1/**", "/backend-service/**").authenticated()
                .and()
            .httpBasic()
                .realmName("serviceGateway")
                .and()
            .csrf()
                .disable()
            .headers()
                .frameOptions().disable()
            .and().addFilterBefore(new SimpleCORSFilter(), ChannelProcessingFilter.class);
    }

}

And my SimpleCORSFilter looks like

public class SimpleCORSFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    /**
     * This method adds specific headers to the HTTP request to enable CORS
     * requests
     * @param request
     * @param response
     * @param chain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse) response;
        res.setHeader("Access-Control-Allow-Origin", "*");
        res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        res.setHeader("Access-Control-Max-Age", "3600");
        res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, x-requested-with, Cache-Control");
        chain.doFilter(request, res);
    }

    @Override
    public void destroy() {

    }
}

I access the code with a simple $http call in Angular

$scope.login = function() {
  $http({
    method: 'GET',
    url: 'https://myservice.mydomain.com:8095/v1/users/login',
    headers: {
      'Authorization': 'Basic ' + btoa("username:password")
    }
  })
    .then(successCallback);
};

I am thinking that putting the CORS filter before security only means that the CORS headers will be added to every request, which doesn't seem like much of a security hole since I send no sensitive data in headers, excepting the Authorization header.

Am I thinking right here or is there something I am not seeing?

Upvotes: 2

Views: 2061

Answers (2)

Abhinav Manthri
Abhinav Manthri

Reputation: 348

In preflight options request, from browser we never get auth token, hence cors filter added before checking authentication should be fine

Upvotes: 0

MvdD
MvdD

Reputation: 23494

I think this is perfectly fine. In fact when your JavaScript code posts to a resource in another origin, the browser will issue a pre-flight request (OPTIONS verb) without the authorization header.

If your authentication code runs before the CORS handler, it has to make an exception for this request, to avoid returning 401 Unauthorized on the pre-flight.

Upvotes: 1

Related Questions