CSRF Tokens
A CSRF token binds a state-changing request to a value that an attacker cannot normally obtain. The server verifies that value before performing the requested action, preventing a malicious site from successfully submitting an authenticated request on the user's behalf.
Cross-Site Request Forgery (CSRF) exploits the browser's automatic inclusion of authentication credentials, such as cookies. An attacker can cause a victim's browser to send a request to another site, but normally cannot read protected responses or obtain unpredictable values from that site because of the same-origin policy.
A synchronizer token defense gives the legitimate application a secret, unpredictable token and requires the token on state-changing requests. The server compares the submitted token with the value associated with the user's session or request context. A forged request from another origin generally cannot supply the correct token because the attacker cannot read it from the legitimate application.
For browser applications, the token can be placed in HTML, embedded in a page-specific response, or exposed through an API designed for the application's own origin. JavaScript can then include it in a request header such as `X-CSRF-Token`. The server must validate the token before processing operations such as changing an email address, transferring funds, or deleting data.
CSRF tokens are primarily relevant when authentication is automatically attached to cross-site requests, especially cookie-based sessions. They are different from authentication tokens themselves: a CSRF token establishes that the request came through an expected application flow, while an authentication credential establishes the user's identity or session.
`SameSite` cookies can reduce CSRF exposure by restricting when cookies are sent cross-site, but they should be treated as a cookie policy rather than as a replacement for understanding the application's CSRF threat model. Applications should also use appropriate origin checks and avoid unsafe state changes through `GET` requests.
Key points
- Use unpredictable CSRF tokens on state-changing operations protected by ambient browser credentials.
- Validate the token server-side before executing the protected operation.
- The attacker can often cause a request but normally cannot read the legitimate site's token.
- CSRF tokens are distinct from authentication credentials.
- `SameSite` cookies can mitigate CSRF but do not eliminate the need for a deliberate CSRF defense strategy.
Interview questions
What is CSRF, and how does a CSRF token prevent it?
CSRF occurs when an attacker causes a user's browser to send a request to an application where the user is already authenticated. The browser may automatically attach session cookies, so the server could otherwise treat the forged request as legitimate. A CSRF token is an unpredictable value that the legitimate application makes available to the client and requires on protected state-changing requests. The attacker generally cannot read that value from the target origin, so the forged request lacks the required token.
Where should a frontend send a CSRF token?
A common design is to send it in a custom request header such as `X-CSRF-Token` for state-changing requests. The application can obtain the value from server-rendered HTML, a trusted same-origin endpoint, or another mechanism appropriate to its architecture. The server then extracts the header and validates the value against the expected token associated with the session or request context. The important property is that an attacker-controlled cross-site request should not be able to obtain and reproduce the valid value.
Are CSRF tokens still necessary when cookies use `SameSite`?
`SameSite` can substantially reduce CSRF risk by restricting when a browser sends cookies in cross-site contexts. However, whether it is sufficient depends on the application's authentication model, required cross-site flows, browser behavior, and threat model. A robust design should explicitly determine which state-changing requests can originate cross-site and use appropriate defenses. CSRF tokens remain a well-established application-level mechanism when the threat model requires them.
Why doesn't CORS by itself prevent CSRF?
CORS primarily governs whether browser JavaScript from one origin can read a response from another origin. CSRF can still work when the attacker does not need to read the response: the attacker only needs the browser to send a state-changing request with the victim's automatically supplied credentials. A server therefore cannot treat CORS as a substitute for request-level CSRF defenses. The application should separately enforce authentication, authorization, and appropriate CSRF or origin protections.
How would you design CSRF protection for a single-page application?
First, I would identify whether the application relies on automatically attached browser credentials, because that determines whether CSRF is a relevant threat. For cookie-authenticated APIs, I would establish a token-delivery mechanism and require the token on every relevant state-changing request, with server-side validation tied to the user's session or another appropriate context. I would also use secure cookie attributes, avoid state changes through `GET`, and consider validating `Origin` or `Referer` where appropriate. Finally, I would test cross-origin requests and failure cases rather than relying only on frontend behavior.