spring-cloud / spring-cloud/spring-cloud-gateway

Register CorsConfigurationSource in GatewayAutoConfiguration

Open
#758 8 comments 8 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Java
Stars
4.9k
Forks
3.5k
Avg merge
20h 57m
Merged PRs (30d)
8

Description

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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading GatewayAutoConfiguration and GlobalCorsProperties to understand how the configured global CORS mappings are exposed. Check how CorsConfigurationSource is consumed after ServerHttpSecurity.cors() is enabled. Done means the existing globalcors.cors-configurations can supply that source automatically for protected-route preflight requests.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring, spring-boot
Domain
api, backend, security
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.