Cross-Site Request Forgery¶
Security objective¶
Prevent another site from causing an authenticated browser to perform a state-changing request. CSRF exploits ambient credentials, not stolen ones.
A request is vulnerable when the browser attaches credentials automatically: session cookies, Basic credentials, or client certificates. Requests authenticated by an explicit Authorization: Bearer header supplied by application code are not automatically attached by the browser.
Why common assumptions fail¶
- "It is a JSON API." Response format does not stop a forged request.
- "The cookie is HttpOnly." The browser still sends it.
- "CORS protects us." CORS restricts reading responses and triggers preflight only for non-simple requests; it is not a general CSRF defense.
- "We only use POST." Forged POSTs are trivial to issue.
Spring Security model¶
| Responsibility | Spring API |
|---|---|
| Enable protection | csrf() (default on for stateful chains) |
| Token storage | CsrfTokenRepository, CookieCsrfTokenRepository |
| SPA cookie handling | CookieCsrfTokenRepository.withHttpOnlyFalse() |
| Token resolution | CsrfTokenRequestHandler |
| Selective exemption | csrf().ignoringRequestMatchers(...) |
| Test token | SecurityMockMvcRequestPostProcessors.csrf() |
Spring ignores safe methods such as GET and HEAD and enforces the token on state-changing methods.
Decision guide¶
| Authentication style | CSRF requirement |
|---|---|
| Cookie session, server-rendered | Synchronizer token required |
| Cookie session, SPA/BFF | Token required, readable by the SPA |
| Bearer token in a header from application code | Generally not required |
| Basic auth in a browser | Required |
Disabling CSRF globally to fix a broken browser flow is a security regression. Exempt narrowly and document why.
Trust and failure cases¶
- Global disable applied to cookie-authenticated endpoints
- State-changing GET endpoints
- Token exposed in URLs or logs
- Login and logout excluded from protection
- Token not rotated with the session
Transfer¶
Every framework must bind a state-changing request to proof of same-site origin. Spring's repository and request-handler abstractions are framework-specific.
Continue with LAB-007.