Spring Security CORS configuration with Spring Boot tutorial — Complete Guide
A practical, in-depth guide to Spring Security CORS configuration with Spring Boot tutorial with examples.
INTRO
When you expose a Spring Boot API to a front‑end SPA (React, Angular, Vue) you’ll quickly run into the dreaded CORS error. The browser refuses to send the request because the server’s response lacks the proper Access‑Control‑Allow‑Origin header, and you’re left scrambling through documentation to find the right combination of @CrossOrigin, CorsConfigurationSource, and Spring Security filters.
The problem isn’t just “add a header”. In a production‑grade service you have to balance security (don’t open your API to the whole internet) with usability (allow the exact origins your UI runs on, support pre‑flight OPTIONS, and keep the configuration DRY). Mis‑configuring CORS in Spring Security can silently break authentication, expose sensitive endpoints, or force you to disable CSRF just to get things working.
That’s why a focused, step‑by‑step guide matters. It shows how to wire CORS correctly inside the Spring Security filter chain, how to keep the configuration testable, and how to avoid the common pitfalls that turn a simple GET request into a nightmare of 403s and 401s.
WHAT YOU'LL LEARN
- How Spring Security’s
CorsFilterinteracts with the globalWebMvcConfigurerCORS setup. - The minimal, production‑ready Java configuration that lets you whitelist multiple origins, methods, and headers.
- Why placing
http.cors()beforehttp.csrf()matters for pre‑flight requests. - How to expose custom headers (e.g.,
Authorization) without breaking the browser’s security model. - Techniques for testing CORS locally with
curland Postman, and verifying the response headers in the browser. - A checklist of common mistakes (duplicate filters,
@CrossOriginon controllers, mismatchedallowedOriginsvsallowedOriginPatterns) and how to fix them.
A SHORT CODE SNIPPET
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
);
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of("https://app.example.com", "https://admin.example.com"));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE"));
config.setAllowedHeaders(List.of("*"));
config.setExposedHeaders(List.of("Authorization"));
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
}
This snippet shows the core idea: define a CorsConfigurationSource bean and plug it into the security chain with http.cors(). The rest of the guide expands on each line, explains why csrf is disabled for simplicity, and shows how to keep it enabled in real deployments.
KEY TAKEAWAYS
-
CORS belongs in the security filter chain, not just in
WebMvcConfigurer; otherwise pre‑flight OPTIONS requests will be blocked before they reach your controller. -
allowedOriginPatternsis safer thanallowedOriginswhen you need wildcard sub‑domains, but it still requires explicit intent—don’t fall back to"*"in production. -
Order matters:
http.cors()must be declared before any request‑matching rules that could reject the pre‑flight request. -
Testing is essential; use
curl -i -X OPTIONSwith the appropriateOriginandAccess-Control-Request-Methodheaders to verify that the server returns the expected CORS headers.
👉 Read the complete guide with step-by-step examples, common mistakes, and production tips:
Spring Security CORS configuration with Spring Boot tutorial — Complete Guide
Top comments (0)