Compare the synchronizer-token pattern (HttpSessionCsrfTokenRepository) with the double-submit cookie approach (CookieCsrfTokenRepository). When would you pick each?
answer
- session store vs cookie store
- double-submit = header equals cookie
- withHttpOnlyFalse() for SPA JS read
- XSRF-TOKEN cookie / X-XSRF-TOKEN header
- stateless & multi-instance -> cookie repo
basics
~20 sSynchronizer token stores the secret server-side in the HttpSession (needs a session). CookieCsrfTokenRepository is stateless double-submit: the token lives in a cookie and is echoed back in a header. Use the cookie repo for SPAs/stateless or multi-instance setups.
solid answer
~40 sThe default **synchronizer-token pattern** keeps the token in server state via `HttpSessionCsrfTokenRepository`; the `CsrfFilter` compares the submitted token against the session copy. It's simple and robust but requires a session, which complicates horizontal scaling and pure-JS clients. **`CookieCsrfTokenRepository`** implements the **double-submit cookie** variant: the token is written to a cookie (`XSRF-TOKEN`) and the client resends it as the `X-XSRF-TOKEN` header; the filter checks the header equals the cookie — no server state. Use `CookieCsrfTokenRepository.withHttpOnlyFalse()` so JavaScript can read the cookie in SPAs (Angular/axios do this automatically). Choose the session repo for classic server-rendered apps with sessions; choose the cookie repo for SPAs, stateless services, or multi-instance deployments without sticky sessions. The double-submit approach trusts same-origin policy to keep the attacker from reading/setting the cookie, and can be weakened by subdomain takeover.
code
java · 9 lines@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(a -> a.anyRequest().authenticated())
.csrf(csrf -> csrf
// Stateless double-submit cookie; withHttpOnlyFalse so a SPA can read it
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()));
return http.build();
}go deeper
Know that one stores the token in the session and one in a cookie.
Explain double-submit mechanics, withHttpOnlyFalse, and the SPA use case.
Weigh statelessness vs the subdomain/XSS weaknesses of double-submit and how SS6 hardens it.
Tie the repository choice to session topology, multi-tenant subdomain risk, and the overall token-handling strategy.
## Two ways to store the CSRF secret Spring Security's `CsrfTokenRepository` abstraction has two production implementations. ### 1. Synchronizer token — `HttpSessionCsrfTokenRepository` (default) - The canonical **synchronizer token pattern**: the server generates a random token, stores it **in the `HttpSession`**, and expects it echoed back on unsafe requests. - `CsrfFilter` loads the expected value from the session and compares it to the request's header/`_csrf` parameter. - **Pros:** the secret never fully lives client-side; no reliance on the client re-presenting a cookie value honestly; conceptually simple. - **Cons:** requires **server-side session state**. In a horizontally scaled deployment you need sticky sessions or a shared session store (Spring Session + Redis). Pure API/JS clients must fetch the token from a rendered page or bootstrap endpoint. ### 2. Double-submit cookie — `CookieCsrfTokenRepository` - The token is stored in a **cookie** (default name `XSRF-TOKEN`) instead of the session. The client reads the cookie and sends the value back in a header (default `X-XSRF-TOKEN`). The filter validates that **header value == cookie value** — hence "double submit". - **Stateless:** no session needed, so it scales cleanly across instances. - Use `CookieCsrfTokenRepository.withHttpOnlyFalse()` when a **SPA** must read the cookie from JavaScript (an HttpOnly cookie is unreadable by JS). Frameworks like Angular and axios auto-read `XSRF-TOKEN` and set `X-XSRF-TOKEN`. - **Security model:** it relies on the **same-origin policy** — an attacker on another origin cannot read your response body to learn the token, and (for the classic variant) cannot set your cookie. Because it's not tied to the session, its guarantee is weaker: a **subdomain takeover** or an XSS on any sibling subdomain that can write cookies for the parent domain can undermine it. Modern Spring mitigates the plain double-submit weakness by combining the cookie token with BREACH-protecting request handling (see the SS6 token-handling question). ## Which to choose | Situation | Pick | |---|---| | Server-rendered app (Thymeleaf), already has sessions | `HttpSessionCsrfTokenRepository` (default) | | SPA + separate JSON API, cookie-based auth | `CookieCsrfTokenRepository.withHttpOnlyFalse()` | | Stateless / multi-instance, no sticky sessions | `CookieCsrfTokenRepository` | | Pure bearer-token API, no cookies | Neither — disable CSRF | ## Gotchas - `withHttpOnlyFalse()` intentionally makes the cookie JS-readable — that's required for SPAs but means the token is exposed to any XSS; fix XSS separately, CSRF tokens are not an XSS defense. - The CSRF cookie is **not** the auth cookie; it is safe (even necessary) for JS to read the CSRF cookie, unlike the session cookie which stays HttpOnly. - With the cookie repo you still need to ensure the cookie is actually written to the response (SS6 defers token loading — see the SPA filter pattern).
- Why does the SPA variant use withHttpOnlyFalse(), and what's the downside?So client JavaScript can read the XSRF-TOKEN cookie and copy it into the X-XSRF-TOKEN header. The downside is the token becomes readable by any XSS on the page — but CSRF tokens were never an XSS defense, so you address XSS separately.
- What weakens the double-submit cookie approach compared to server-side synchronizer tokens?It trusts that no attacker can write cookies for your domain. A subdomain takeover or an XSS on a sibling subdomain that can set a parent-domain cookie can inject a matching token into both cookie and header.
saying these in an interview costs you the question
- Saying CookieCsrfTokenRepository requires a server session
- Claiming the CSRF cookie must be HttpOnly (it can't be for SPA reads)
- Confusing the CSRF cookie with the auth/session cookie
- Believing double-submit is strictly as strong as the session-backed synchronizer token