JWT Refresh Token Rotation: Sicheres Muster für reale Systeme

Die meisten JWT-Tutorials hören bei „Verwenden eines Aktualisierungstokens für langlebige Sitzungen“ auf. Sie erklären selten, was passiert, wenn das Aktualisierungstoken gestohlen wird. Ein statisches Aktualisierungstoken – eines, das sich nie ändert – gewährt einem Angreifer den gleichen dauerhaften Zugriff wie ein gestohlenes Sitzungscookie. Schlimmer noch, es gibt keine Möglichkeit, den Diebstahl zu erkennen.
Aktualisierungstokenrotation löst dieses Problem, indem bei jeder Verwendung ein neues Aktualisierungstoken ausgegeben wird. Wenn ein alter Token erneut abgespielt wird, wird die gesamte Sitzung widerrufen. In diesem Artikel wird das von Auth0, Okta und anderen seriösen Identitätsanbietern verwendete Implementierungsmuster erläutert.
Warum statische Aktualisierungstoken fehlschlagen
Ein statisches Aktualisierungstoken hat einen festen Wert für die gesamte Sitzungslebensdauer (häufig mehr als 30 Tage). Probleme:
- Der Diebstahl geschieht still – wenn ein Angreifer das Aktualisierungstoken stiehlt, kann er unbegrenzt neue Zugriffstoken generieren, ohne dass der Benutzer es weiß
- Keine Wiederholungserkennung – derselbe Token kann wiederholt von verschiedenen Standorten aus verwendet werden
- Der Widerruf ist grob – um einen gestohlenen Token ungültig zu machen, müssen Sie oft alle Benutzersitzungen ungültig machen
Die Lösung besteht darin, jedes Aktualisierungstoken als Einmal-Token zu behandeln.
Das Rotationsmodell
Schritt 1: Anmelden – Erstellen Sie eine Token-Familie
Wenn sich der Benutzer authentifiziert, generieren Sie eine family_id (UUID), die alle Token in dieser Sitzung gruppiert:
{ family_id: "f47ac10b-58cc-4372-a567-0e02b2c3d479", user_id: "user_123", refresh_token_hash: sha256(refresh_token), created_at: "2026-03-28T10:00:00Z", expires_at: "2026-04-27T10:00:00Z", used: false
}Speichern Sie diesen Datensatz serverseitig. Speichern Sie niemals Aktualisierungstoken im lokalen Speicher – verwenden Sie httpOnly Cookies oder sicheren nativen Speicher.
Schritt 2: Token-Aktualisierung – Rotate
Wenn der Client das Aktualisierungstoken vorlegt:
- Suchen Sie den Token-Hash in der Datenbank
- Stellen Sie sicher, dass es zu einer aktiven Familie gehört und nicht als
used markiert ist.
- Markieren Sie es als
used: true - Stellen Sie ein neues Aktualisierungstoken aus (neuer Zufallswert, gleicher
family_id) - Ein neues Zugriffstoken ausstellen
- Speichern Sie den neuen Aktualisierungstoken-Hash
Schritt 3: Wiederholungserkennung
Wenn ein als used: true markiertes Aktualisierungstoken erneut angezeigt wird, bedeutet dies entweder:
- Ein Angreifer spielt einen gestohlenen Token erneut ab, oder
- Ein legitimer Client versucht es nach einem Netzwerkfehler erneut.
Die sichere Antwort: alle Token in der Familie widerrufen. Dadurch wird der Benutzer gezwungen, sich erneut anzumelden. Es ist besser, einem legitimen Benutzer einmal Unannehmlichkeiten zu bereiten, als einem Angreifer den Zugriff zu überlassen.
// Wiederholung erkannt – nukleare Option
warte auf db.query( 'LÖSCHEN AUS REfresh_tokens WHERE Family_id = $1', [Familien-ID]
);Datenbankschema
Eine minimale Aktualisierungstokentabelle:
CREATE TABLE restart_tokens ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), Familien-ID UUID NICHT NULL, user_id UUID NICHT NULL REFERENZEN Benutzer(id), token_hash TEXT NICHT NULL EINZIGARTIG, verwendet BOOLEAN DEFAULT FALSE, erstellt_at TIMESTAMPTZ DEFAULT now(), läuft ab_at TIMESTAMPTZ NICHT NULL, ersetzt_durch UUID-REFERENZENfresh_tokens(id)
); CREATE INDEX idx_refresh_family ON restart_tokens(family_id);
INDEX ERSTELLEN idx_refresh_user ON restart_tokens(user_id);Die Spalte replaced_by erstellt eine Kette, der Sie zu Prüfzwecken folgen können.
Verarbeitung gleichzeitiger Anfragen
In echten Anwendungen können mehrere API-Aufrufe gleichzeitig eine Aktualisierung auslösen. Wenn Anruf A den Token rotiert, während Anruf B noch den alten besitzt, löst Anruf B die Wiederholungserkennung aus – der Benutzer wird unerwartet abgemeldet.
Grace Period Pattern
Ermöglichen, dass das vorherige Aktualisierungstoken nach der Rotation für ein kurzes Fenster (5–10 Sekunden) gültig bleibt:
const GRACE_PERIOD_MS = 10_000; if (token.used) { const elapsed = Date.now() - token.rotated_at; if (abgelaufen < GRACE_PERIOD_MS) { // Within grace period — return the already-issued new tokens return getLatestTokensForFamily(token.family_id); } // Outside grace period — replay attack await revokeFamily(token.family_id); throw new UnauthorizedError('token_replayed');
}Überwachung und Warnungen
Verfolgen Sie diese Signale in der Produktion:
- Ereignisse pro Stunde wiederholen – ein Spitzenwert weist auf einen aktiven Angriff oder einen clientseitigen Fehler hin
- Familiensperrungen – hohe Raten können auf Token-Diebstahl oder einen falsch konfigurierten Client hinweisen
- Aktualisierungsrate pro Benutzer – ungewöhnlich hohe Raten deuten auf Token-Harvesting hin
- Geografische Anomalien – Aktualisierung aus einem anderen Land als dem ursprünglichen Login
Aktualisierungstoken vs. Zugriffstoken: Kurzreferenz
| Property | Zugriffstoken | Aktualisierungstoken |
|---|---|---|
| Lifetime | 5–15 Minuten | 7–30 Tage |
| Format | JWT (eigenständig) | Undurchsichtige Zeichenfolge (empfohlen) |
| Storage | Speicher (JS-Variable) | httpNur Cookie |
| Gesendet an | API-Server | Nur Auth-Server |
| Rotation | Nicht erforderlich | Jede Verwendung |
Informationen zu Zeitanspruchsvalidierungsfehlern, die häufig mit Aktualisierungsflüssen interagieren, finden Sie unter JWT exp/iat/nbf common bugs.
FAQ
Wie soll ich mit gleichzeitigen Aktualisierungsanfragen umgehen?
Verwenden Sie einen kurzen Kulanzzeitraum (5–10 Sekunden), in dem das vorherige Aktualisierungstoken weiterhin akzeptiert wird. Dies behandelt Race-Bedingungen, wenn mehrere API-Aufrufe gleichzeitig eine Aktualisierung auslösen. Nach Ablauf der Kulanzfrist ist nur das neueste Token gültig.
Sollten Aktualisierungstoken JWT oder undurchsichtige Zeichenfolgen sein?
Undurchsichtige Zeichenfolgen sind im Allgemeinen sicherer für Aktualisierungstoken. JWTs transportieren Nutzdaten, die die Angriffsfläche erhöhen, und Aktualisierungstoken müssen nicht eigenständig sein, da der Server sie ohnehin immer in der Datenbank nachschlägt.
Wie lange sollten Aktualisierungssitzungen aktiv sein?
7–30 Tage sind typisch. Hochsichere Anwendungen (Bankwesen, Gesundheitswesen) sollten 1–7 Tage dauern. Verbraucher-Apps können mit Rotation bis zu 90 Tage laufen. Kombinieren Sie lange Sitzungen immer mit Geräte-Fingerprinting und Anomalieerkennung.
Verwandte Tools und Artikel
- JWT Decoder – Token prüfen und Zeitansprüche überprüfen
- JWT-Sicherheitsfehler – häufige JWT-Fallstricke über Aktualisierungstoken hinaus
- JWT Time-Claim-Fehler – Probleme mit der Uhrabweichung und der Validierungsreihenfolge
- 2FA-Leitfaden – Authentifizierung über Token hinaus stärken