How to Fix CORS Issues in Spring Gateway Security
Cross-Origin Resource Sharing (CORS) is a critical aspect of modern web applications, especially when your frontend and backend are hosted on different origins. In this blog post, we’ll explore how to configure CORS in a Spring Gateway with security and ensure it works seamlessly.
Common CORS Issue Scenario
You might encounter the following error when making cross-origin requests from a frontend application:
Access to XMLHttpRequest at 'https://api.example.com/resource' from origin 'https://frontend.example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
While testing APIs in Postman works fine, the browser enforces CORS policies, leading to this error when integrating with a frontend.
Typical Causes
Missing or incorrect CORS configuration.
Conflicts between Spring Security and global CORS settings.
Preflight
OPTIONS
requests not handled properly.
Let’s walk through the solution.
Step-by-Step Solution
1. Enable CORS in Spring Gateway Security
When using Spring Security, it’s essential to integrate CORS configuration directly within your SecurityWebFilterChain
to ensure preflight requests are handled correctly.
Here’s a concise solution:
@Bean
public SecurityWebFilterChain securityFilterChain(ServerHttpSecurity httpSecurity) {
return httpSecurity
.cors(cors -> cors.configurationSource(request -> {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*"); // Replace '*' with specific origins in production
config.addAllowedMethod("*");
config.addAllowedHeader("*");
config.setAllowCredentials(true); // Optional, if credentials are used
return config;
}))
.csrf(ServerHttpSecurity.CsrfSpec::disable)
.authorizeExchange(authorize -> authorize
.pathMatchers(
"/public-endpoints/**", "/swagger-ui/**", "/v3/api-docs/**"
).permitAll()
.anyExchange().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()))
.build();
}
Key Highlights
Inline CORS Configuration: Tying the
CorsConfigurationSource
directly tohttpSecurity.cors()
ensures Spring Security handles CORS requests properly.Allow Credentials: Enable this only if you’re dealing with cookies or authorization headers that require credentials.
2. Using Global CORS Configuration
Spring Gateway provides a global CORS configuration option in application.yml
that can also handle CORS for all routes. However, this might conflict with Spring Security settings if not done correctly.
application.yml
server:
servlet:
context-path: /
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "*" # Replace with specific origins for production
allowedMethods: "*"
allowedHeaders: "*"
While this approach is simpler, ensure that the SecurityWebFilterChain
does not disable CORS (.cors(ServerHttpSecurity.CorsSpec::disable)
) to avoid conflicts.
3. Debugging and Testing CORS
If you’re still facing issues, follow these debugging steps:
Check the Preflight Request
A CORS preflight is an OPTIONS
request sent by the browser to verify CORS permissions. Test it using curl
:
curl -X OPTIONS \
-H "Origin: https://frontend.example.com" \
-H "Access-Control-Request-Method: GET" \
https://api.example.com/resource -I
Ensure the response includes headers like:
Access-Control-Allow-Origin: https://frontend.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Inspect Gateway Logs
Enable debug logs for Spring Gateway to see how requests are routed and whether CORS headers are being set:
logging:
level:
org.springframework.cloud.gateway: DEBUG
Verify with Browser DevTools
Use browser developer tools to inspect network requests. Look for the OPTIONS
request and verify the response headers.
4. Avoiding Common Pitfalls
Do Not Use
*
for Credentials: Ifconfig.setAllowCredentials(true)
is set, avoid using*
forallowedOrigins
. Specify exact origins instead.Example:
config.setAllowedOrigins(List.of("https://frontend.example.com"));
Downstream Services: If the gateway forwards requests to other services, ensure those services also handle CORS properly.
Version Compatibility: Ensure you’re using compatible versions of Spring Boot, Spring Cloud Gateway, and Spring Security.
Conclusion
Fixing CORS issues in a Spring Gateway with security involves careful coordination between Spring Security and the gateway’s global CORS configuration. The recommended approach is to configure CORS directly within the SecurityWebFilterChain
to ensure proper handling of preflight requests.
By following the steps outlined above, you can eliminate CORS-related errors and enable seamless cross-origin communication for your applications.
Happy coding! 🚀
Subscribe to my newsletter
Read articles from Shohanur Rahman directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Shohanur Rahman
Shohanur Rahman
👋 Hey there! I’m Shohanur Rahman! I’m a backend developer with over 5.5 years of experience in building scalable and efficient web applications. My work focuses on Java, Spring Boot, and microservices architecture, where I love designing robust API solutions and creating secure middleware for complex integrations. 💼 What I Do Backend Development: Expert in Spring Boot, Spring Cloud, and Spring WebFlux, I create high-performance microservices that drive seamless user experiences. Cloud & DevOps: AWS enthusiast, skilled in using EC2, S3, RDS, and Docker to design scalable and reliable cloud infrastructures. Digital Security: Passionate about securing applications with OAuth2, Keycloak, and digital signatures for data integrity and privacy. 🚀 Current Projects I’m currently working on API integrations with Spring Cloud Gateway and designing an e-invoicing middleware. My projects often involve asynchronous processing, digital signature implementations, and ensuring high standards of security. 📝 Why I Write I enjoy sharing what I’ve learned through blog posts, covering everything from backend design to API security and cloud best practices. Check out my posts if you’re into backend dev, cloud tech, or digital security!