Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Zuul Proxy CORS header contains multiple values, headers repeated twice - Java Spring Boot CORS filter config

Why would I be getting every CORS header doubled? I am using the Zuul Proxy to have the request to a service proxied through an API gateway.

I must have something misconfigured with my spring security filtering order.

When I access a route that requires authentication I am getting an error like:

Request to service through API Gateway error

XMLHttpRequest cannot load https://myservice.mydomain.com:8095/service/v1/account/txHistory?acctId=0.  
The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed. 
Origin 'http://localhost:9000' is therefore not allowed access.

Chrome network log

I checked the response in Chrome devtools and sure enough the CORS headers are repeated twice: CORS Headers repeated

So this looks like somehow my CORS filter is being called twice for each reply. I don't know why that would be happening at this point. It could be that my filter is added before the ChannelProcessingFilter.

Code for API Gateway CORS filter:

public class SimpleCORSFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) 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() {}
}

My API Gateway security configuration:

@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").permitAll()
                .antMatchers("/mappings", "/v1/**", "/service/**").authenticated()
                .and()
            .httpBasic()
                .realmName("apiRealm")
                .and()
            .csrf()
                .disable()
            .headers()
                .frameOptions().disable()
            .and().addFilterBefore(new SimpleCORSFilter(), ChannelProcessingFilter.class);
    }

}

I could solve this by checking if the header is null and then setting it only if it is empty or null, though that does not seem like the best solution. I would like to understand what I have done to cause the headers to be preset twice.

like image 910
Kent Bull Avatar asked Mar 16 '16 17:03

Kent Bull


2 Answers

I also had the same issue, and i added the CorsFilter into the class where has @ EnableZuulProxy, but it still didn't solve my problem.

According to the github Q&A Zuul Access-Control-* Headers are duplicated

zuul.ignored-headers=Access-Control-Allow-Credentials, Access-Control-Allow-Origin

To add it to my zuul's bootstrap.properties, it works!!!

like image 118
Java Basketball Avatar answered Oct 23 '22 07:10

Java Basketball


I had a similar problem but the issue was that I had CORS filter in both APIGateway and other services. IF thats not your case then try this CORS filter.

Add this to the class where you have @EnableZuulProxy in the API Gateway. This should do the trick i have a similar configuration on mine.

@Bean
public CorsFilter corsFilter() {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("OPTIONS");
    config.addAllowedMethod("HEAD");
    config.addAllowedMethod("GET");
    config.addAllowedMethod("PUT");
    config.addAllowedMethod("POST");
    config.addAllowedMethod("DELETE");
    config.addAllowedMethod("PATCH");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}
like image 41
Grinish Nepal Avatar answered Oct 23 '22 06:10

Grinish Nepal