Server-side safety
Protect cookie-authenticated forms from CSRF
Understand cross-site request forgery and combine SameSite cookies, CSRF tokens, and origin checks according to the application’s needs.
8 minute lesson
Cross-site request forgery matters when the browser attaches authentication automatically, usually through cookies.
Imagine you are signed in to bank.test. Another site can create a form that posts to https://bank.test/transfers. The browser may attach matching bank cookies even though the form came from another site.
The request is authenticated, but the user did not intend it.
Start with the HTTP contract:
- GET and other safe requests must not change data.
- State-changing requests use POST or another appropriate method.
- Session cookies use a suitable
SameSitepolicy. - Sensitive endpoints require a CSRF defense chosen for the application’s architecture.
A common server-rendered pattern uses a random token tied to the user’s session:
<form action="/account/email" method="post">
<input name="csrfToken" type="hidden" value="random-session-token">
<!-- email field and submit button -->
</form>
The server compares the submitted token with the expected token before changing the email. The attacker can submit a form, but cannot read a correctly protected page to obtain the token.
The token must be unpredictable, checked on the server, and handled without leaking it into logs or external URLs. A hidden input is not secret from the person using the page; its value is useful because another origin cannot normally read it.
Origin checks can add another layer. Verify the Origin header, or carefully fall back to Referer when your design requires it. Do not accept a missing or mismatched origin blindly on sensitive operations.
SameSite cookies reduce risk but are not a reason to ignore the rest of the design. Cross-origin requirements, older clients, and application architecture affect the right combination.
CSRF defenses do not fix cross-site scripting. Script running in your own origin may be able to read tokens and submit requests.
Try posting to a protected endpoint without a token, with a wrong token, and with the correct token. Only the last request should change state.
Lesson completed