flowCreate.solutions

CSRF (Frontend Standard)

This document defines the CSRF protection standard for Next.js apps using cookie-based authentication.

Why CSRF matters here

Because the browser automatically sends cookies, an attacker can sometimes trigger authenticated requests from a malicious site. CSRF protections are required for all unsafe methods:

  • POST, PUT, PATCH, DELETE

Required layers (defense-in-depth)

For every unsafe request hitting the BFF (/api/v1/*), enforce:

  1. SameSite cookies
    • Prefer SameSite=Lax.
    • Use SameSite=Strict only if product flows allow it.
  2. CSRF token requirement
    • Use a token that the attacker cannot read/copy cross-site.
  3. Origin/Referer checks
    • Reject unsafe requests when Origin/Referer does not match your own origin.

Standard pattern: double-submit token

This pattern is simple and works well for BFFs:

  • Server sets a non-HttpOnly CSRF cookie (so browser JS can read it) e.g., csrf_token.
  • Client sends the token in a header (or body) e.g., X-CSRF-Token.
  • BFF rejects if:
    • cookie missing, or header missing
    • header token != cookie token
    • origin/referrer mismatch

Rule: the CSRF token must be independent from auth cookies and must be validated on the server.

  • Cookie: csrf_token
  • Header: X-CSRF-Token

Projects may rename these, but must document it.

Standard BFF validation algorithm (pseudocode)

function validateCsrf(req: Request): void {
  if (!isUnsafeMethod(req.method)) return

  assertSameOrigin(req.headers.get("origin"), req.headers.get("referer"))

  const csrfCookie = readCookie(req, "csrf_token")
  const csrfHeader = req.headers.get("x-csrf-token")

  if (!csrfCookie || !csrfHeader) throw new Error("CSRF token missing")
  if (!timingSafeEqual(csrfCookie, csrfHeader)) throw new Error("CSRF token mismatch")
}

Notes

  • CSRF validation is standardized in the Next.js BFF.
  • The backend may add its own CSRF protections, but the minimum bar is enforced at the BFF.