A cookie-authenticated SPA must send a CSRF value in a non-cookie request part, then obtain a fresh value after authentication transitions.
Spring Security SPA CSRF: refresh the token after login and logout
A cookie is not the proof
Browsers attach login cookies automatically to cross-site requests. A state-changing receipt command therefore needs a separate CSRF token in a header or form field. Copying the login cookie into another cookie proves nothing. CookieCsrfTokenRepository can expose an XSRF-TOKEN cookie and read X-XSRF-TOKEN from a request header, but the JavaScript app must actually send the header. Session CSRF is the base boundary; a pure bearer API has a different credential model.
Handle token lifecycle
Spring Security can defer loading a token until needed, and its request handling includes protection against token disclosure attacks. A single-page client reading the cookie needs the SPA-specific handler strategy for the raw cookie value. Authentication success and logout clear the old token; the client must fetch a fresh token before its next unsafe request. Spring Security 7 spa() configures the server-side SPA token handling; the client still makes the refresh call. Do not solve a post-login 403 by disabling CSRF for all application routes. Keep a small same-origin token bootstrap endpoint or response contract.
Test in a browser-shaped client
Attempt POST with the session cookie and no header; expect denial. Repeat with a matching token header; expect success. Then log in or out and confirm the old token no longer authorizes a write. Test cross-origin credential settings separately because CORS controls which origins may read responses, not whether a forged write is valid. A regular HTTP client test must explicitly model cookie and header behavior.
Implementation contract
http.csrf(csrf -> csrf.spa());
// The SPA sends the issued token in X-XSRF-TOKEN on unsafe requests.Cost and verification
Token generation and comparison are small, but session or cookie loading adds per-request work. A bootstrap call after login adds one round trip; it preserves the write boundary.
Common Mistakes
- Do not rely on SameSite alone for every browser and deployment topology.
- Do not disable CSRF globally because the SPA receives 403 after login.
- Do not treat CORS approval as a CSRF defense.
Read next
Spring Security CSRF: protect cookie-authenticated writes, Spring Security bearer POST and CSRF: define the credential boundary, Spring Security OAuth2 login: callback, identity and browser session, Spring Security CORS preflight: evaluate origin before authentication, Spring Session cookie policy: SameSite, Secure and the reverse proxy.
