Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring Security CORS preflight: evaluate origin before authentication

Last updated: 5 Oct 20264 min read
tutorial
IntermediateBy AITrove Editorial

An OPTIONS preflight lacks ordinary credentials; configure a bounded CORS policy in the security chain before protected requests reach authorization.

Preflight is not the business request

A browser sends OPTIONS with an Origin and requested method before some cross-origin API calls. That preflight may have no session cookie or bearer token. Rejecting it for missing authentication prevents the browser from making a later valid POST. Spring Security can process CORS before authorization when a suitable configuration source is wired. The browser boundary] still does not replace server-side authentication.

Name allowed callers precisely

Accept one configured web origin, the required methods, and the exact headers used by the client. A wildcard origin with credentialed requests is a dangerous mismatch and may be rejected by browser rules. The example uses an environment-provided origin and does not permit credentials by default; a cookie-based application needs a separate, reviewed CSRF and cookie policy. Session CSRF] and bearer-token APIs should not be mixed casually.

Probe both requests

Send an OPTIONS request with a permitted Origin, Access-Control-Request-Method POST and Access-Control-Request-Headers Authorization. Assert the response permits the browser to continue without authenticating the preflight. Then send the actual POST without a valid token and require denial; a successful preflight grants no write access. Repeat with an unapproved origin and with multiple filter chains], since the selected chain controls the CORS policy.

Implementation contract

Java
@Bean
UrlBasedCorsConfigurationSource apiCors(
        @Value("${app.web-origin}") String webOrigin) {
    CorsConfiguration policy = new CorsConfiguration();
    policy.setAllowedOrigins(List.of(webOrigin));
    policy.setAllowedMethods(List.of("GET", "POST", "OPTIONS"));
    policy.setAllowedHeaders(List.of("Authorization", "Content-Type"));
    UrlBasedCorsConfigurationSource source =
        new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/api/**", policy);
    return source;
}

@Bean
SecurityFilterChain apiChain(HttpSecurity http) throws Exception {
    http.securityMatcher("/api/**")
        .cors(Customizer.withDefaults())
        .authorizeHttpRequests(rules ->
            rules.anyRequest().authenticated());
    return http.build();
}

Cost and verification

Preflight adds an extra browser round trip unless cached. A narrow policy costs little server CPU, but every new origin, method or header expands the cross-origin surface and should correspond to a real client requirement.

Common Mistakes

  • Do not require a bearer token on the OPTIONS preflight and then call the browser broken.
  • Do not treat a successful preflight as authorization for the actual request.
  • Do not apply a broad origin wildcard to a credentialed browser flow.

Read next

Spring MVC CORS: a browser-origin policy is not authentication, Spring Security filter chain: authentication, CSRF and request order, Spring Security request matchers: order rules and cover the fallback, Spring Security CSRF: protect cookie-authenticated writes, Spring MockMvc security test: run the application filter chain.

Related security contract

Spring Security CSP rollout: enforce tested asset rules at the response edge.

spring
spring-boot
security
cors-preflight-security-order
Storage details