← Zurück zum Blog

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

Entwicklersicherheit28. März 2026·9 Minuten Lesezeit
JWT refresh token rotation diagram

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:

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:

  1. Suchen Sie den Token-Hash in der Datenbank
  2. Stellen Sie sicher, dass es zu einer aktiven Familie gehört und nicht als used
  3. markiert ist.
  4. Markieren Sie es als used: true
  5. Stellen Sie ein neues Aktualisierungstoken aus (neuer Zufallswert, gleicher family_id)
  6. Ein neues Zugriffstoken ausstellen
  7. Speichern Sie den neuen Aktualisierungstoken-Hash

Schritt 3: Wiederholungserkennung

Wenn ein als used: true markiertes Aktualisierungstoken erneut angezeigt wird, bedeutet dies entweder:

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:

Aktualisierungstoken vs. Zugriffstoken: Kurzreferenz

PropertyZugriffstokenAktualisierungstoken
Lifetime5–15 Minuten7–30 Tage
FormatJWT (eigenständig)Undurchsichtige Zeichenfolge (empfohlen)
StorageSpeicher (JS-Variable)httpNur Cookie
Gesendet anAPI-ServerNur Auth-Server
RotationNicht erforderlichJede 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