Cross‑Site Request Forgery (CSRF) bleibt einer der am häufigsten genutzten Angriffsvektoren in Web‑Anwendungen. Obwohl Frameworks wie Next.js viele Mechanismen bereitstellen, die den Aufbau sicherer Schnittstellen erleichtern, übersehen Entwickler oft grundlegende Schutzmaßnahmen. In diesem Artikel zeigen wir Schritt für Schritt, wie man eine Next.js‑Anwendung vor CSRF schützt, indem man SameSite-Cookies und das Muster double‑submit token kombiniert. Wir erläutern das Bedrohungsmodell, die Funktionsweise, Code‑Beispiele, eine Migrations‑Checkliste und typische Fallstricke.
Bedrohungsmodell – wie ein CSRF‑Angriff aussieht
Ein CSRF‑Angriff nutzt den autorisierten Kontext des Browsers des Opfers. Der Nutzer ist in der Anwendung eingeloggt und besucht anschließend eine bösartige Seite, die eine HTTP‑Anfrage an einen geschützten Endpunkt sendet (z. B. POST /api/transfer). Der Browser fügt automatisch die Sitzungs‑Cookies hinzu, sodass der Server die Anfrage als authentisch betrachtet. Ohne einen zusätzlichen Verifizierungsmechanismus kann der Server diese Anfrage nicht von einer legitimen Benutzeraktion unterscheiden.
Warum SameSite‑Cookies allein nicht ausreichen
Das Setzen des Flags SameSite=Lax oder SameSite=Strict im Sitzungs‑Cookie verhindert dessen automatisches Senden im Cross‑Site‑Kontext. In der Praxis gibt es jedoch Szenarien, in denen Browser das Cookie trotzdem senden (z. B. GET-Anfragen im Lax-Modus oder nicht unterstützte ältere Browser). Deshalb wird empfohlen, SameSite mit einem zusätzlichen Token zu kombinieren, das serverseitig geprüft wird.
Double‑submit token – Funktionsprinzip
Das Double‑Submit‑Token‑Muster erzeugt ein zufälliges Token auf dem Server und übermittelt es sowohl im Cookie als auch im Header (oder im Request‑Body). Der Server vergleicht bei eingehender Anfrage die beiden Werte – stimmen sie überein, wird die Anfrage als authentisch akzeptiert. Das Token muss nicht serverseitig gespeichert werden (stateless), was die Skalierbarkeit vereinfacht.
„Das doppelte Token ist der einfachste Weg, eine starke CSRF‑Verifizierung einzuführen, ohne serverseitige Sitzungen zu verwenden.“
Implementierung in Next.js – Server‑Teil
Next.js stellt API‑Routes bereit, die als Server‑Funktionen fungieren. Im Folgenden ein Code‑Snippet, das ein Token erzeugt, es in einem SameSite=Lax-Cookie speichert und bei nachfolgenden Anfragen prüft.
import { NextApiRequest, NextApiResponse } from 'next';
import crypto from 'crypto';
const CSRF_COOKIE = 'csrfToken';
const CSRF_HEADER = 'x-csrf-token';
function generateToken() {
return crypto.randomBytes(32).toString('hex');
}
export default function handler(req: NextApiRequest, res: NextApiResponse) {
// 1️⃣ Token bei GET erzeugen (z. B. beim Rendern eines Formulars)
if (req.method === 'GET') {
const token = generateToken();
res.setHeader('Set-Cookie', `${CSRF_COOKIE}=${token}; HttpOnly; SameSite=Lax; Path=/; Secure`);
return res.status(200).json({ csrfToken: token });
}
// 2️⃣ Verifizierung bei POST/PUT/DELETE
const cookieToken = req.cookies[CSRF_COOKIE];
const headerToken = req.headers[CSRF_HEADER];
if (!cookieToken || !headerToken || cookieToken !== headerToken) {
return res.status(403).json({ error: 'Invalid CSRF token' });
}
// … weitere Logik des Endpunkts
return res.status(200).json({ success: true });
}
Im obigen Beispiel wird das Token beim ersten GET erzeugt und sowohl im Cookie als auch in der JSON‑Antwort zurückgegeben. Der Client (z. B. eine React‑Komponente) sollte das Token auslesen und bei nachfolgenden mutierenden Anfragen im Header x-csrf-token mitsenden.
Implementierung in Next.js – Client‑Teil (React)
In React‑Komponenten können wir den Hook useEffect nutzen, um das Token abzurufen und den Standard‑Header in axios oder fetch zu setzen. Beispiel mit fetch:
import { useEffect } from 'react';
export default function useCsrf() {
useEffect(() => {
fetch('/api/csrf')
.then(r => r.json())
.then(data => {
// Token ist in data.csrfToken und im Cookie verfügbar
window.csrfToken = data.csrfToken;
});
}, []);
}
export async function csrfFetch(url, options = {}) {
const headers = {
...options.headers,
'x-csrf-token': window.csrfToken,
};
return fetch(url, { ...options, headers, credentials: 'include' });
}
Das Setzen von credentials: 'include' sorgt dafür, dass das Cookie mit dem Token an die Anfrage angehängt wird, während der Header x-csrf-token die doppelte Verifizierung ermöglicht.
Checklisten zur CSRF‑Minderung in Next.js
- Setzen Sie das Flag
SameSite=Lax(oderStrict, wenn die Anwendung keine cross‑site POST‑Requests benötigt) sowieSecurein jedem Sitzungs‑Cookie. - Generieren Sie ein eindeutiges Token pro Sitzung und speichern Sie es in einem http‑only Cookie.
- Senden Sie das Token in einem dedizierten Header (
x-csrf-token) bei allen mutierenden Requests. - Vergleichen Sie auf Serverseite Cookie‑ und Header‑Token, bevor geschäftslogische Aktionen ausgeführt werden.
- Begrenzen Sie die Lebensdauer des Tokens (z. B. 30 Minuten) und erneuern Sie es bei jeder neuen Sitzung.
- Stellen Sie sicher, dass alle API‑Endpunkte, die Daten empfangen (POST, PUT, DELETE, PATCH), CSRF‑Prüfungen aktiviert haben.
Typische Fehler und Kompromisse
Entwickler machen häufig folgende Fehler:
- Fehlendes
SameSite-Flag – in älteren Browsern kann das Token ausgenutzt werden, was den Schutz schwächt. - Verwendung eines nicht‑httpOnly‑Cookies – ermöglicht bösartigen Skripten das Auslesen des Tokens und eliminiert den Nutzen des doppelten Tokens.
- Speichern des Tokens im Local Storage – macht es anfällig für Diebstahl durch XSS.
- Nur clientseitige Token‑Prüfung – bietet keinen echten Schutz, da ein Angreifer den JavaScript‑Code umgehen kann.
- Setzen von
SameSite=Strictin einer Anwendung, die externe Links benötigt – kann legitime Anfragen unerwartet ablehnen.
In der Praxis ist die Kombination von SameSite und Double‑Submit‑Token am sichersten, ergänzt durch das Prinzip des least‑privilege – minimieren Sie Cookie‑ und Token‑Rechte und beschränken Sie deren Geltungsbereich auf notwendige Pfade (Path=/api).
Verweise auf Standards und Best Practices
Die beschriebenen Techniken entsprechen den OWASP‑Richtlinien Top 10 – A05:2021 – Security Misconfiguration sowie CWE‑352 (Cross‑Site Request Forgery). Zusätzlich wird das Setzen von SameSite und das least‑privilege-Prinzip im OWASP Secure Headers Project empfohlen. Die Implementierung des Double‑Submit‑Tokens erfüllt die Anforderung OWASP ASVS 2.2.1 (CSRF Prevention).
Praktisches Beispiel – kompletter API‑Code und React‑Hook
Unten finden Sie ein vollständiges, sofort kopierbares Beispiel, das Sie in /pages/api/csrf.ts sowie in Ihrem Hook /hooks/useCsrf.ts einsetzen können. Damit haben Sie gleichzeitig einen Endpunkt, der das Token erzeugt, und eine einfache Funktion für gesicherte Requests.
// /pages/api/csrf.ts
import { NextApiRequest, NextApiResponse } from 'next';
import crypto from 'crypto';
const COOKIE_NAME = 'csrfToken';
const HEADER_NAME = 'x-csrf-token';
function newToken() {
return crypto.randomBytes(24).toString('base64');
}
export default function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'GET') {
const token = newToken();
res.setHeader('Set-Cookie', `${COOKIE_NAME}=${token}; HttpOnly; SameSite=Lax; Secure; Path=/; Max-Age=1800`);
return res.status(200).json({ csrfToken: token });
}
const cookieToken = req.cookies[COOKIE_NAME];
const headerToken = req.headers[HEADER_NAME];
if (!cookieToken || !headerToken || cookieToken !== headerToken) {
return res.status(403).json({ error: 'Invalid CSRF token' });
}
// hier kommt die Logik des geschützten Endpunkts
return res.status(200).json({ message: 'Protected action succeeded' });
}
// /hooks/useCsrf.ts
import { useEffect } from 'react';
export function useCsrf() {
useEffect(() => {
fetch('/api/csrf', { credentials: 'include' })
.then(r => r.json())
.then(data => {
(window as any).csrfToken = data.csrfToken;
});
}, []);
}
export async function csrfFetch(input: RequestInfo, init: RequestInit = {}) {
const token = (window as any).csrfToken;
const headers = new Headers(init.headers);
headers.set('x-csrf-token', token);
return fetch(input, { ...init, headers, credentials: 'include' });
}
Nachdem Sie useCsrf in einer Komponente importiert haben, wird das Token beim Mounten geladen und jede Verwendung von csrfFetch fügt automatisch den erforderlichen Header hinzu.
Fazit und nächste Schritte
Der Schutz vor CSRF in Next.js‑Anwendungen erfordert keine komplexen Lösungen – das Kombinieren von SameSite-Cookies, Secure-Flags und dem Double‑Submit‑Token‑Muster reicht aus. Wenn Sie nach OWASP, CWE und dem Prinzip des least‑privilege arbeiten, schaffen Sie eine robuste Barriere gegen unautorisierte Requests. Für Sicherheits‑Audits, Integrations‑Support oder das Anheben des Schutzniveaus Ihrer gesamten Plattform kontaktieren Sie Coderia.it – gemeinsam bauen wir eine Anwendung, die den neuesten Bedrohungen standhält.



