FSD Frontend System Design

Part II β€” The Shield Β· Lesson 3.15

Cross-Site Request Forgery (CSRF)

In one lineAnother site makes the user's browser send an authenticated request β€” cookies attach automatically.

Where you've seen itA hidden auto-submitting form on an unrelated page, POSTing to your bank while your session cookie is still valid.

  • Time16 min
  • DiagramAttack flow + SameSite and token defences
  • Chapter3 Β· Security

Diagram

diagram
THE ATTACK β€” the browser is the confused deputy

  1. user logs into bank.com        cookie stored
  2. user visits evil.com           (same browser, same day)
  3. evil.com contains:

       <form action="https://bank.com/transfer" method="POST">
         <input name="to"     value="attacker">
         <input name="amount" value="50000">
       </form>
       <script>document.forms[0].submit()</script>

  4. browser sends the POST ──► bank.com
                                 └── cookie attached AUTOMATICALLY
  5. server sees a valid session ──► transfer executes

  The attacker never reads the response. They don't need to.
diagram
WHY CORS DOESN'T SAVE YOU

  CORS blocks READING a cross-origin response.
  CSRF only needs the WRITE to happen.

  form POST ──► sent, blocked from reading ──► damage already done
diagram
DEFENCES β€” layered, cheapest first

  1. SameSite cookies       Lax  = not sent on cross-site POST     βœ“ default
                            Strict = not sent on any cross-site nav
                            None = sent always (requires Secure)

  2. CSRF token             server issues per-session/per-form token,
                            attacker can't read it (same-origin policy)
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”  form + hidden token  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚ Client β”‚ ────────────────────► β”‚ Server β”‚ compare with session
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜

  3. Origin / Referer check server rejects mismatched Origin header

  4. Re-authenticate        password or OTP for destructive actions

How it works

  1. Cookies are attached by the browser based on destination, not on who initiated the request.
  2. So any site can cause an authenticated write unless something proves the request came from your UI.
  3. SameSite=Lax (now the browser default) stops cross-site POSTs while keeping normal top-level navigation working.
  4. CSRF tokens remain necessary where SameSite=None is required (embedded flows, some SSO) β€” the double-submit cookie pattern is the common implementation.
  5. Authorization: Bearer headers are not auto-attached, so token-in-header APIs are structurally CSRF-immune β€” but then you're exposed to XSS token theft instead (see 3.5).

Trade-offs

DefenceStrengthCost
SameSite=LaxBlocks most CSRFBreaks legitimate cross-site POST flows
SameSite=StrictStrongestUser arrives from a link already "logged out"
CSRF tokenWorks with NoneServer state or signed double-submit
Origin checkSimple, effectiveSome proxies strip the header

Interview angle

"Are you safe from CSRF if your API uses JWT in an Authorization header?"

  • Structurally yes, because the browser never attaches that header automatically.
  • But storing the JWT where JS can read it hands it to any XSS β€” you traded one risk for another.
  • The balanced answer: HttpOnly + Secure + SameSite=Lax cookies, plus a CSRF token on state-changing routes.

Recap

  • CSRF abuses automatic cookie attachment; it needs the write, not the read.
  • SameSite=Lax closes most of it; tokens cover the rest.
  • Header-based auth avoids CSRF but moves the risk to XSS β€” pick deliberately.