Cross-Site Request Forgery (CSRF)
CSRF tricks a logged-in user's browser into making an authenticated request to your site without the user intending it. The attack works because browsers automatically attach credentials — usually cookies — to requests, even ones triggered by a malicious page.
CSRF is fundamentally a cookie-based auth problem. If your app authenticates requests with Authorization: Bearer tokens that the browser doesn't send automatically, classic CSRF risk largely disappears (though you then inherit XSS-token-theft concerns instead).
TL;DR
- If you use cookie-based auth, you must defend against CSRF.
- A strong baseline:
SameSite=Laxcookies + an anti-CSRF token on state-changing requests + anOrigincheck. - CORS does not prevent CSRF — it controls who can read responses, not who can send requests.
- Bearer-token APIs (no cookies) carry little classic CSRF risk.
Quick Example
The two layers that stop most CSRF — a SameSite session cookie plus a token on unsafe methods:
The server rejects any state-changing request whose token is missing or doesn't match.
How CSRF Works
Typical targets are high-value, state-changing actions: changing an email or password, adding a payment method, transferring funds, or deleting data.
When You're Vulnerable
You're at meaningful CSRF risk when all of these hold:
- Authentication relies on cookies the browser sends automatically.
- Endpoints perform state-changing actions.
- The server doesn't require additional proof of intent (a token or origin check).
⚠️ CORS is not a CSRF defense. A cross-site
POSTcan still be sent without CORS letting the attacker read the response — and for a destructive action, sending is enough.
Defenses (layered)
1. SameSite cookies
Set session cookies Secure, HttpOnly, and SameSite=Lax (or Strict if your UX allows). Lax blocks cookies on most cross-site requests while still allowing top-level navigations. Apps that need cross-site cookies must use SameSite=None; Secure, which raises the importance of the other layers.
2. Anti-CSRF tokens
For unsafe methods (POST/PUT/PATCH/DELETE): the server issues a token tied to the session, the client returns it in a header or form field, and the server validates it. The token must not be readable by third-party sites.
3. Origin / Referer checks
For unsafe methods, require the Origin header to match your site (fall back to a strict Referer check). This catches many attacks even if token wiring has a bug.
4. Double-submit cookie (stateless)
When you can't store server-side token state: set a random CSRF cookie and require the same value echoed in a request header. A third-party site can't read the cookie to copy it. Works best combined with SameSite.
Choosing a Defense
SPA Notes
- Cookie-authenticated SPA on the same site: send a token in an
X-CSRF-Tokenheader and rotate it per session. - Bearer-token SPA (token in memory, no auth cookies): classic CSRF mostly doesn't apply — but protect that token from XSS.
Common Mistakes
Protecting only some endpoints
Relying on CORS or a JSON content type
FAQ
Do I need CSRF protection if I use JWTs in an Authorization header?
Generally no for classic CSRF — the browser doesn't auto-attach Authorization headers, so a cross-site request can't ride the user's credentials. You do still need to protect the token from XSS. The risk returns if you store the JWT in a cookie that's sent automatically.
Is SameSite=Lax enough on its own?
It's a strong baseline and blocks most cross-site sends, but it isn't complete — older browsers, SameSite=None flows, and some request types weaken it. Combine it with tokens and an Origin check.
Does CORS protect against CSRF?
No. CORS governs whether JavaScript may read a cross-origin response; it doesn't stop the request from being sent. A forged state-changing request can succeed regardless of CORS.
Which methods need CSRF protection?
State-changing ones: POST, PUT, PATCH, DELETE. Safe, idempotent reads (GET/HEAD) shouldn't change state, so they don't — and you should never perform mutations on a GET.
Related Topics
- Cross-Site Scripting (XSS) — Often chained with or replacing CSRF
- Security Headers — Cookie and origin hardening
- API Security — Token vs cookie auth trade-offs
- Authentication — Session and cookie design