5 min read

CSRF protection in Next.js — when you need it, when you don't

Next.js App Router apps often skip CSRF protection because they think SameSite cookies are enough. They are not always enough. Here is the specific rule.

CSRF (Cross-Site Request Forgery) lets an attacker trigger a state-changing request in your app from a different origin while the victim is logged in. Modern browsers default to SameSite=lax cookies, which blocks most CSRF — but not all.

What it is

If your app authenticates via cookies and a state-changing action can be triggered by a GET or by a simple-content-type POST from a different origin, you are vulnerable. CSRF tokens verify the request originated from your own form.

Vulnerable example

// Vulnerable: any origin can POST a form that changes user email.
export async function POST(req: Request) {
  const form = await req.formData();
  const email = form.get("email") as string;
  const session = await getSession(); // cookie-based
  await prisma.user.update({ where: { id: session.userId }, data: { email } });
  return Response.redirect("/settings");
}

Fixed example

// Fixed: verify a double-submit CSRF token
import { cookies, headers } from "next/headers";

export async function POST(req: Request) {
  const form = await req.formData();
  const fromForm = form.get("csrf_token");
  const fromCookie = (await cookies()).get("csrf_token")?.value;
  if (!fromForm || fromForm !== fromCookie) {
    return new Response("csrf", { status: 403 });
  }
  // ...continue
}

How Securie catches it

Securie's CSRF specialist maps every state-changing handler against its cookie-auth surface and requires an explicit CSRF defense — either a verified origin check, a token, or a non-cookie auth scheme.

Checklist

  • State-changing routes (POST/PUT/PATCH/DELETE) have CSRF defense if auth is cookie-based
  • Header-based auth (Bearer token in Authorization) does not need CSRF tokens for same-reason protection
  • SameSite=lax is the baseline; pair with an origin/referer check for sensitive routes
  • GET requests never change state
  • Form actions in Server Components use a signed token

FAQ

Do I need CSRF tokens if I use NextAuth?

NextAuth has built-in CSRF protection. Your own endpoints outside NextAuth still need their own defense.