spring-cloud / spring-cloud-gateway

An API Gateway built on Spring Framework and Spring Boot providing routing and more.
http://cloud.spring.io
Apache License 2.0
4.52k stars 3.32k forks source link

Register CorsConfigurationSource in GatewayAutoConfiguration #758

Open msassak opened 5 years ago

msassak commented 5 years ago

When using SCG with Spring Security, the CORS support provided by SCG is only a partial solution. Public routes permitted by the security config work as expected, but protected routes do not, as the security config executes before the CORS configuration, causing preflight CORS requests to those resources to be denied.

Enabling Spring Security's CORS support is easy. This solves the problem, but not before defining a CorsConfigurationSource bean from the content of GlobalCorsProperties. I was surprised to find that this was not done automatically by SCG when spring.cloud.gateway.globalcors.cors-configurations had already been defined. If this is the correct way to handle this (it appears to work as expected now), it would be a useful addition to SCG.

This is with Greenwich.M3, Spring Boot 2.1.0 and Spring Security 5.1.1.

For example, given the global CORS configuration from application.yml:

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowed-origins:
            - "https://foo.example.com"
            - "http://localhost:8080"
            allowed-methods:
            - "*"
            allowed-headers:
            - "*"
            allow-credentials: true

And the security configuration class:

@EnableWebFluxSecurity
@Configuration
public class SecurityConfig {

    @Bean
    public SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http)
            throws Exception {
        // @formatter:off
        http.cors().and()
            .authorizeExchange()
            .pathMatchers("/public/route/1", "/public/route/2").permitAll()
            .anyExchange().authenticated()
            .and().oauth2ResourceServer().jwt();
        // @formatter:on
        return http.build();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource(
            GlobalCorsProperties globalCorsProperties) {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        globalCorsProperties.getCorsConfigurations()
                .forEach(source::registerCorsConfiguration);
        return source;
    }
}

Once .cors() is called on the ServerHttpSecurity object, the CorsConfigurationSource takes care of the rest.

If possible, it'd be great to see something like this in a future release of Spring Cloud Gateway. Thanks!

Links

tony-clarke-amdocs commented 5 years ago

PR's are welcome. It would be great if the PR included a unit test that only passes with the additional functionality provided by the PR.

msassak commented 5 years ago

Thanks. It'll take me a while to get to it, but I'll give it a shot when I have some time.

mlubavin-vg commented 3 years ago

I finally found this after hours banging my head on why OPTIONS requests were being blocked for my secured routes. Workaround works great and its nice that it reads from the global configuration to reduce code duplication

rob-valor commented 1 year ago

@ryanjbaxter , is it still an option to add it to this project? We also were stuck on this issue for several hours because of the assumption that Spring Boot auto-configuration handles that for us... :wink: . The upside of this story: we got better insight into the config and CORS itself :laughing:

ViliusS commented 11 months ago

We spent a fair amount of hours debugging this. At least documentation should be improved regarding CORS usage in Gateway as currently it doesn't do justice.

StevenPG commented 10 months ago

My team just spent a good amount of time debugging this as well, completely believed auto-configuration handled this. There should be examples of working projects, had to derive the answer from vague SO posts displaying both CorsConfiguration bean and GlobalCorsProperties in yaml.

Sithira commented 10 months ago

I wasted my entire day to figure this one out. i think this should be added to auto-configuration 🥲

drunkcattt commented 8 months ago

+1