← Terug naar blog

JWT Tokenrotatie vernieuwen: veilig patroon voor echte systemen

Beveiliging voor ontwikkelaars28 maart 2026·9 min leestijd
JWT refresh token rotation diagram

De meeste JWT-tutorials stoppen bij 'gebruik een vernieuwingstoken voor langdurige sessies'. Ze leggen zelden uit wat er gebeurt als dat vernieuwingstoken wordt gestolen. Een statisch vernieuwingstoken (een token dat nooit verandert) geeft een aanvaller dezelfde permanente toegang als een gestolen sessiecookie. Erger nog, er is geen manier om de diefstal te detecteren.

Vernieuwingstokenrotatie lost dit op door bij elk gebruik een nieuw vernieuwingstoken uit te geven. Als een oud token opnieuw wordt afgespeeld, wordt de hele sessie ingetrokken. In dit artikel wordt het implementatiepatroon besproken dat wordt gebruikt door Auth0, Okta en andere serieuze identiteitsproviders.

Waarom statische vernieuwingstokens mislukken

Een statisch vernieuwingstoken heeft een vaste waarde voor de gehele sessieduur (vaak meer dan 30 dagen). Problemen:

De oplossing is om elk vernieuwingstoken te behandelen als eenmalig gebruik.

Het rotatiemodel

Stap 1: Inloggen — Maak een tokenfamilie

Wanneer de gebruiker zich authenticeert, genereert u een family_id (UUID) die alle tokens in deze sessie groepeert:

{ 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
}

Sla deze record op de server op. Bewaar vernieuwingstokens nooit in localStorage. Gebruik httpOnly cookies of beveilig de eigen opslag.

Stap 2: Token vernieuwen — Roteren

Wanneer de client het vernieuwingstoken presenteert:

  1. Zoek de token-hash op in de database
  2. Controleer of het tot een actieve familie behoort en niet is gemarkeerd als used
  3. Markeer het als gebruikt: waar
  4. Geef een nieuw vernieuwingstoken uit (nieuwe willekeurige waarde, dezelfde family_id)
  5. Een nieuw toegangstoken uitgeven
  6. Sla de nieuwe vernieuwingstoken-hash op

Stap 3: Herhalingsdetectie

Als een vernieuwingstoken gemarkeerd als used: true opnieuw wordt weergegeven, betekent dit:

Het veilige antwoord: alle tokens in de familie intrekken. Hierdoor wordt de gebruiker gedwongen opnieuw in te loggen. Het is beter om een legitieme gebruiker één keer lastig te vallen dan een aanvaller toegang te laten behouden.

// Herhaling gedetecteerd: nucleaire optie
wacht op db.query( 'VERWIJDEREN VAN refresh_tokens WAAR family_id = $1', [familie-ID]
);

Databaseschema

Een minimale vernieuwingstokentabel:

TABEL MAKEN refresh_tokens ( id UUID PRIMAIRE SLEUTEL STANDAARD gen_random_uuid(), family_id UUID NIET NULL, user_id UUID NIET NULL REFERENTIES gebruikers(id), token_hash TEKST NIET NULL UNIEK, gebruikte BOOLEAN STANDAARD ONWAAR, aangemaakt_op TIMESTAMPTZ DEFAULT nu(), vervalt_om TIMESTAMPTZ NIET NULL, vervangen_door UUID REFERENTIES refresh_tokens(id)
); MAAK INDEX idx_refresh_family AAN refresh_tokens(family_id);
INDEX MAKEN idx_refresh_user AAN refresh_tokens(user_id);

De kolom vervangen_door creëert een keten die u kunt volgen voor auditdoeleinden.

Gelijktijdige verzoeken afhandelen

In echte toepassingen kunnen meerdere API-aanroepen tegelijkertijd een vernieuwing activeren. Als oproep A het token roteert terwijl oproep B de oude nog vasthoudt, activeert oproep B herhalingsdetectie, waardoor de gebruiker onverwacht wordt uitgelogd.

Respijtperiodepatroon

Toestaan dat het vorige vernieuwingstoken geldig blijft gedurende een korte periode (5-10 seconden) na rotatie:

const GRACE_PERIOD_MS = 10_000; if (token.gebruikt) { const verstreken = Datum.nu() - token.rotated_at; als (verstreken < 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');
}

Monitoring en waarschuwingen

Volg deze signalen tijdens de productie:

Token vernieuwen versus toegangstoken: snelle referentie

EigenschapToegangstokenToken vernieuwen
Levensduur5–15 minuten7–30 dagen
FormaatJWT (op zichzelf staand)Ondoorzichtige tekenreeks (aanbevolen)
OpslagGeheugen (JS-variabele)httpAlleen cookie
Verzonden naarAPI-serversAlleen authenticatieserver
RotatieNiet nodigElk gebruik

Voor bugs in de validatie van tijdclaims die vaak interactie hebben met vernieuwingsstromen, zie JWT exp/iat/nbf veelvoorkomende bugs.

Veelgestelde vragen

Hoe moet ik gelijktijdige vernieuwingsverzoeken afhandelen?

Gebruik een korte respijtperiode (5-10 seconden) waarbij het vorige vernieuwingstoken nog steeds wordt geaccepteerd. Hiermee worden raceomstandigheden afgehandeld wanneer meerdere API-aanroepen tegelijkertijd een vernieuwing activeren. Na de respijtperiode is alleen het nieuwste token geldig.

Moeten vernieuwingstokens JWT of ondoorzichtige tekenreeksen zijn?

Ondoorzichtige tekenreeksen zijn over het algemeen veiliger voor vernieuwingstokens. JWT's bevatten payloadgegevens die het aanvalsoppervlak vergroten, en vernieuwingstokens hoeven niet op zichzelf te staan, aangezien de server ze toch altijd in de database opzoekt.

Hoe lang moeten vernieuwingssessies live zijn?

7–30 dagen is gebruikelijk. Hoogbeveiligde toepassingen (banken, gezondheidszorg) zouden 1 tot 7 dagen nodig hebben. Consumenten-apps kunnen bij rotatie maximaal 90 dagen meegaan. Combineer lange sessies altijd met apparaatvingerafdrukken en afwijkingsdetectie.

Gerelateerde tools en artikelen