What is CORS, and how do you enable it in a Spring Security application?
answer
- http.cors(Customizer.withDefaults())
- CorsConfigurationSource bean named corsConfigurationSource
- browser-only, opt-in via Access-Control-Allow-*
- filter chain runs before MVC
- UrlBasedCorsConfigurationSource per path
basics
~20 sCORS lets a browser page from one origin call an API on another origin. In Spring Security you turn it on with http.cors() in the SecurityFilterChain and provide a CorsConfigurationSource bean that lists allowed origins, methods, and headers.
solid answer
~30 sCORS (Cross-Origin Resource Sharing) is a browser rule: JavaScript on origin A (scheme+host+port) may only read a response from origin B if B sends Access-Control-Allow-* headers permitting it. In Spring Security you enable it inside the SecurityFilterChain with http.cors(Customizer.withDefaults()). That activates Spring Security's CorsFilter, which reads a CorsConfigurationSource bean (usually named corsConfigurationSource). You typically register a UrlBasedCorsConfigurationSource with a CorsConfiguration specifying setAllowedOrigins, setAllowedMethods, setAllowedHeaders, and optionally setAllowCredentials. Without http.cors(), Spring Security ignores your CORS config for anything the filter chain protects, and the preflight OPTIONS request can be blocked by authorization before your controller ever runs.
code
java · 23 lines@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors(Customizer.withDefaults()) // wires in the CorsFilter using the bean below
.authorizeHttpRequests(auth -> auth.anyRequest().authenticated());
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"));
config.setAllowedHeaders(List.of("Authorization", "Content-Type"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
}go deeper
Must know CORS is a browser cross-origin rule and that http.cors() plus a CorsConfigurationSource bean enables it.
Should explain why the security chain (not @CrossOrigin) is the right place and what the source bean contains.
Should distinguish CORS from authz and know the bean-name resolution and per-path source mapping.
Frames CORS as one browser-side control among many, and reasons about same-origin deployment as the way to avoid it entirely.
## What CORS is An **origin** is the triple scheme + host + port (e.g. `https://app.example.com:443`). Browsers enforce the **Same-Origin Policy**: JavaScript loaded from origin A cannot, by default, read responses from origin B. **CORS (Cross-Origin Resource Sharing)** is the standard by which server B *opts in* to being called cross-origin by sending `Access-Control-Allow-*` response headers. CORS is enforced entirely by the **browser** — a non-browser client (curl, another server) ignores it. So CORS is not authentication or authorization; it only controls which web pages may *read* your responses in a browser. ## Enabling it in Spring Security Spring Security has its own CORS integration because the **security filter chain runs before Spring MVC**. You enable it in your `SecurityFilterChain`: ```java http.cors(Customizer.withDefaults()); ``` `Customizer.withDefaults()` tells the `CorsConfigurer` to look up a bean of type `CorsConfigurationSource` (by default the bean named `corsConfigurationSource`) and install a `CorsFilter` into the chain that uses it. ## The CorsConfigurationSource bean ```java @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(List.of("https://app.example.com")); config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE")); config.setAllowedHeaders(List.of("Authorization", "Content-Type")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; } ``` `CorsConfiguration` is the object that becomes the `Access-Control-Allow-*` headers. `UrlBasedCorsConfigurationSource` maps URL patterns to configurations, so you can have different rules per path. ## Why not just @CrossOrigin or a WebMvcConfigurer? `@CrossOrigin` on a controller and `WebMvcConfigurer.addCorsMappings` configure CORS at the **MVC layer**, which sits *after* the security filter chain. If Spring Security rejects the request first (for example a preflight `OPTIONS` that has no credentials), your controller-level CORS config never runs. That is why, when Spring Security is on the classpath, you must configure CORS through `http.cors()` so the `CorsFilter` sits inside the security chain. ## Common gotchas - Forgetting `http.cors()` — the bean exists but is never wired into the security chain. - Wrong bean name/type — `Customizer.withDefaults()` resolves `CorsConfigurationSource`; a mismatched name is silently ignored. - Setting allowed origins to `*` together with credentials (illegal — covered in a separate question). ## When to use Any time a browser SPA served from one origin (e.g. `localhost:3000` or a CDN domain) calls your Spring API on a different origin. If the UI and API share an origin (same host/port, e.g. served behind one reverse proxy), you do not need CORS at all.
- Does CORS protect your server from malicious clients?No. CORS is enforced by the browser and only governs whether page JavaScript may read a response. A non-browser client (curl, another backend) ignores CORS entirely, so it is not a substitute for authentication/authorization.
- What happens if you define the CorsConfigurationSource bean but forget http.cors()?The security filter chain never installs the CorsFilter, so no Access-Control-Allow-* headers are added and cross-origin browser calls fail. The bean is effectively dead configuration.
saying these in an interview costs you the question
- Claiming CORS blocks malicious/non-browser clients or replaces authentication
- Saying @CrossOrigin alone is enough when Spring Security is present
- Thinking CORS is a server-to-server restriction rather than a browser policy