CORS Configuration with Spring Security
Fast recall
Quick revision
Core answer
DispatcherServlet. Enable CORS in `SecurityFilterChain` with `.cors(...)`, then define allowed origins, methods, and headers in a `CorsConfigurationSource` bean. Without this, preflight `OPTIONS` requests are rejected with 401/403 before reaching MVC config — the most common CORS bug. `allowCredentials(true)` is incompatible with wildcard origins — enumerate exact origins or use allowedOriginPatterns. CORS is browser-only; backend-to-backend calls ignore it entirely.Whether the candidate understands the interaction between the security filter chain and CORS — a common source of production bugs.
Only adding @CrossOrigin on controllers or configuring WebMvcConfigurer and wondering why the API still returns CORS errors in production.
Explain why preflight OPTIONS requests carry no credentials and must be permitted, and discuss environment-specific CORS policies.
Interview-ready guide
Interview answer
The layering problem
- Request -> Spring Security filter chain -> DispatcherServlet -> Spring MVC
- A CORS preflight (OPTIONS) rejected at filter chain returns 403/401 before MVC sees it
WebMvcConfigurer.addCorsMappings()alone is insufficient when Spring Security is present
Correct configuration
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http, CorsConfigurationSource corsSource) throws Exception {
http.cors(cors -> cors.configurationSource(corsSource));
return http.build();
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of("https://app.example.com"));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}The wildcard + credentials rule
allowedOrigins("*")withallowCredentials(true)violates the CORS spec- Browsers reject it
- Use
allowedOriginPatterns("https://*.example.com")for subdomains with credentials
Why preflight OPTIONS is special
- Browser sends OPTIONS before non-simple cross-origin requests
- No credentials in preflight
- If Spring Security requires auth, OPTIONS gets 401
- Browser sees CORS error and blocks main request
- Solution:
http.cors()registers CORS filter ahead of auth filters; orpermitAll()for OPTIONS
Production rules
- Enumerate exact origins per environment
maxAge(3600)to cache preflights- For microservices: configure at gateway, not per-service
- Use
curl -X OPTIONS -vto debug what headers come back
CORS Configuration with Spring Security
Direct Answer
CORS must be configured in Spring Security, not just in Spring MVC, because the security filter chain intercepts requests before they reach DispatcherServlet. Enable CORS in SecurityFilterChain with .cors(...), then define allowed origins, methods, and headers in a CorsConfigurationSource bean. Without this, preflight OPTIONS requests are rejected with 401/403 before reaching MVC config — the most common CORS bug. allowCredentials(true) is incompatible with wildcard origins — enumerate exact origins or use allowedOriginPatterns. CORS is browser-only; backend-to-backend calls ignore it entirely.
Common Mistakes & Pitfalls
Only adding @CrossOrigin on controllers or configuring WebMvcConfigurer and wondering why the API still returns CORS errors in production.
Check your understanding
Answer these without looking back at the article.
- Why must setAllowCredentials(true) be paired with explicit origins instead of setAllowedOrigins('*')?
- How would you configure different CORS policies for public vs authenticated endpoints?
- When is it safe to use a wildcard origin ('*') in a production API?
- Why doesn't @CrossOrigin work when Spring Security is in the chain?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.