In short
Your browser sends cookies automatically, even when another website triggers the request. CSRF abuses that politeness to make logged-in users do things they never clicked.
Cross-Site Request Forgery — preventing a malicious site from tricking a logged-in user's browser into making unwanted requests to your API using their existing session/cookies.

Think of it like this
The watchman who trusts the flat number
Your society watchman lets in any parcel that says 'For flat 302', because 302 is a known resident. A prankster books twenty fake deliveries to your flat. Now the watchman asks for a secret code that only you could have given. No code, no entry.
Watch it happen
A forged request from another site
login, gets cookie
1/5You log in to your bank. The browser stores a session cookie for bank.example.
The big ideas
What you need to know
Cookies are the weak spot
CSRF only works when auth rides along automatically, as with cookies. A Bearer token you add in JS isn't sent by other sites.
SameSite cookies
SameSite=Lax or Strict tells the browser not to send the cookie on cross-site POSTs. Modern browsers default to Lax.
CSRF tokens
Put a random token in your forms and check it on the server. Other sites can't read your page, so they can't copy it.
GET must not change things
Never delete or transfer on GET. Links and images can fire GET requests from anywhere, and Lax still allows top-level GETs.
See it in code
Walk through the code
1import crypto from "node:crypto";2 3app.get("/transfer", (req, res) => {4 req.session.csrf = crypto.randomBytes(32).toString("hex");5 res.render("transfer", { csrf: req.session.csrf });6});7 8app.post("/transfer", (req, res) => {9 if (!req.session.csrf || req.body._csrf !== req.session.csrf) {10 return res.status(403).send("Bad CSRF token");11 }12 // safe to move money now13});1/2When the real form is shown, the server makes a random token, saves it in the session and puts it in the form.
The form includes a hidden _csrf input with the token. Set session cookies with SameSite=Lax, HttpOnly and Secure as well; layers beat a single lock.
Save yourself the pain
Common mistakes
Oops
Assuming a JSON API with cookie auth can't be hit by CSRF.
Do this instead
If auth is a cookie, think about CSRF. Use SameSite cookies, check the Origin header, or require a token header.
Oops
Setting SameSite=None on the session cookie to fix a login bug.
Do this instead
None removes the protection. Only use it with Secure, and only when a cross-site setup truly needs it.
Your mission
Forge a request against yourself
Quick check
Your SPA sends the JWT in an Authorization header set by JavaScript, with no cookies. How exposed is it to CSRF?
Go deeper
- 1Learn why CSRF specifically targets cookie-based session auth, not token-based auth in headers.
- 2Implement CSRF tokens for a cookie-authenticated form submission.
- 3Understand `SameSite` cookie attributes as a modern, simpler mitigation.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.