Unravel โบ Java concepts โบ Security
CORS and CSRF protection
CORS decides which web pages from other origins may call your API from a browser.
Learn these first
At a glance
CORS is the guest list at the door of your building: which other buildings may send visitors.
- 1The browser enforces the same-origin policyFor a call to another origin it first sends an OPTIONS preflight; the API answers with Access-Control-Allow-Origin, -Methods and -Headers if allowed. The browser then performs or blocks the real request.
- 2In Spring configure it once: a CorsConfigurationSource bean, http.cors(...), or @CrossOrigin on a controllerList explicit origins; allowCredentials(true) cannot be combined with the wildcard *.
- 3CSRF: when authentication rides on cookies, any site can make the browser send the cookieThe server requires an extra token (a cookie XSRF-TOKEN copied into the header X-XSRF-TOKEN by the front end) that a foreign site cannot read.
- 4Token-based APIs that use a Bearer header (not a cookie) are not vulnerable to CSRF, which is why stateless JWT APIs typically disable it
- CORS is a browser rule, not authentication
- Never reflect any Origin header back with credentials allowed, and never allow null origin; both defeat the check
- CorsFilter runs early in the chain, matches the request origin against the configuration and short-circuits preflights with the allow headers
@BeanCorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(List.of("https://app.acme.com")); config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE")); config.setAllowedHeaders(List.of("Authorization", "Content-Type")); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/api/**", config); return source;}- line 2 uses CorsConfiguration, the core of CORS and CSRF protection
- line 3 uses CorsConfiguration, the core of CORS and CSRF protection
- line 8 uses UrlBasedCorsConfigurationSource, the core of CORS and CSRF protection
- line 9 uses CorsConfiguration, the core of CORS and CSRF protection
Read the full explanation (about 2 min)
CORS decides which web pages from other origins may call your API from a browser. CSRF protection stops a malicious site from making the browser send an authenticated request on the user behalf. They are often confused but solve different problems.
A mental model
CORS is the guest list at the door of your building: which other buildings may send visitors. CSRF protection is checking a secret handshake, because a forger could otherwise trick a legitimate resident into signing something.
How it works
The browser enforces the same-origin policy. For a call to another origin it first sends an OPTIONS preflight; the API answers with Access-Control-Allow-Origin, -Methods and -Headers if allowed. The browser then performs or blocks the real request.
In Spring configure it once: a CorsConfigurationSource bean, http.cors(...), or @CrossOrigin on a controller. List explicit origins; allowCredentials(true) cannot be combined with the wildcard *.
CSRF: when authentication rides on cookies, any site can make the browser send the cookie. The server requires an extra token (a cookie XSRF-TOKEN copied into the header X-XSRF-TOKEN by the front end) that a foreign site cannot read.
Token-based APIs that use a Bearer header (not a cookie) are not vulnerable to CSRF, which is why stateless JWT APIs typically disable it.
Going deeper
CORS is a browser rule, not authentication. curl and servers ignore it. A permissive CORS setting does not expose more data to attackers but lets other websites read responses with the visitor credentials, which is the danger.
Never reflect any Origin header back with credentials allowed, and never allow null origin; both defeat the check.
Cookies should use SameSite=Lax or Strict, HttpOnly and Secure, which blocks most CSRF on its own. State-changing operations must never use GET.
Under the hood
CorsFilter runs early in the chain, matches the request origin against the configuration and short-circuits preflights with the allow headers. CsrfFilter loads the expected token from the repository (session or cookie) for each state-changing method and compares it with the one sent in the header or form field, using a constant-time comparison.
Common mistakes
- Wildcard origins with credentials.
- Reflecting the Origin header blindly.
- Disabling CSRF for a cookie-based app.
- Using GET for changes.
How Unravel recognises it
When you paste code, Unravel looks for these signs of cors and csrf protection. Spotting them yourself is a good habit when you read unfamiliar code:
- Annotations:
@CrossOrigin - Types:
CorsConfigurationCorsConfigurationSourceUrlBasedCorsConfigurationSourceCorsFilterCsrfTokenCsrfFilterCookieCsrfTokenRepositoryCsrfTokenRepositoryCsrfTokenRequestAttributeHandlerCorsRegistryHttpSessionCsrfTokenRepository - Method calls:
addCorsMappings()allowedOrigins()allowedOriginPatterns()allowCredentials()csrf()cors()allowedMethods()allowedHeaders() - Configuration keys:
Access-Control-Allow-OriginX-XSRF-TOKEN
Part of a learning path
- Security for backend developers ยท previous: OAuth 2.0 and OpenID Connect login ยท next: Password hashing (BCrypt, Argon2, PBKDF2)
Related concepts
Frequently asked questions
What is CORS and CSRF protection?
CORS decides which web pages from other origins may call your API from a browser. CSRF protection stops a malicious site from making the browser send an authenticated request on the user behalf. They are often confused but solve different problems.
What are the most common mistakes with CORS and CSRF protection?
Wildcard origins with credentials. Reflecting the Origin header blindly. Disabling CSRF for a cookie-based app. Using GET for changes.
How can I see CORS and CSRF protection in real code?
Paste your own Java into Unravel and it will point out where cors and csrf protection appears, explain how it works at the detail level you choose, and draw the flow of the code around it.