JWT exp/iat/nbf Fouten: tijdclaim-bugs die de authenticatie verbreken

JWT tijdclaims — exp, iat en nbf — zijn bedrieglijk eenvoudig. Het zijn gewoon Unix-tijdstempels. Toch veroorzaken ze een aantal van de meest frustrerende authenticatiefouten in de productie: tokens die te snel verlopen, tokens die op de ene server werken maar niet op een andere, en tokens die helemaal nooit verlopen.
Dit artikel behandelt de meest voorkomende tijdclaimbugs, waarom ze optreden en hoe je ze kunt oplossen met veilige standaardinstellingen.
Hoe exp, iat en nbf werken
Elke JWT kan drie tijdgerelateerde claims in zijn payload meenemen:
- exp (Vervaltijd) — het token MOET NIET worden geaccepteerd na deze tijdstempel
- iat (uitgegeven op) — toen het token werd gemaakt
- nbf (niet eerder) — het token MOET NIET worden geaccepteerd vóór deze tijdstempel
Alle drie zijn numerieke datums: het aantal seconden sinds 1970-01-01T00:00:00Z (Unix-tijdperk). Geen milliseconden – seconden. Dit onderscheid alleen al veroorzaakt grofweg 20% van alle JWT-tijdbugs.
Gebruik onze JWT-decoder om tijdclaims in elk token onmiddellijk te inspecteren.
Bug #1: Milliseconden gebruiken in plaats van seconden
JavaScript's Date.now() retourneert milliseconden. De JWT-specificatie vereist seconden. Door exp in te stellen op Date.now() + 3600000 wordt een token gemaakt dat vervalt in het jaar 2089, niet binnen één uur.
// FOUT — milliseconden
const exp = Datum.nu() + 3600000; // CORRECT — seconden
const exp = Math.floor(Datum.nu() / 1000) + 3600;De meeste JWT-bibliotheken verwerken dit intern, maar als u handmatig payloads samenstelt, is dit het eerste dat u moet controleren.
Bug #2: exp-claim volledig ontbreken
Als u vergeet exp in te stellen, zullen veel bibliotheken graag een token maken dat nooit verloopt. Dit is een veiligheidsrisico: een gelekt token blijft voor altijd geldig.
Stel altijd exp in. Valideer het altijd op de server. Als uw bibliotheek standaard tokens zonder exp niet afwijst, configureert u dit zo.
// Node.js jsonwebtoken — vervaldatum afdwingen
jwt.verify(token, geheim, { maxAge: '1h' });Bug #3: Klokafwijking tussen servers
Server A geeft een token uit om 14:00:00 uur. De klok van server B geeft 13:59:55 aan (5 seconden achter). Als het token nbf: 1711540800 (14:00:00) heeft, wijst Server B het af als "nog niet geldig."
Dit komt vooral veel voor in:
- Microservice-architecturen met niet-gesynchroniseerde klokken
- Serverloze functies waarbij containers een klokafwijking hebben
- Mobiele apps waarbij de apparaatklok handmatig wordt ingesteld
De oplossing
Laat een kleine kloktolerantie toe (ook wel 'speelruimte' genoemd) — doorgaans 30-60 seconden:
// jsonwebtoken
jwt.verify(token, geheim, { clockTolerance: 30 }); // jose (Node.js)
wachten jwtVerify(token, sleutel, { clockTolerance: '30s' });Stel de tolerantie nooit boven de 2 minuten in. Als je meer nodig hebt, repareer dan je NTP-synchronisatie.
Bug #4: Verkeerde validatiebestelling
De juiste validatievolgorde is belangrijk. Als je de handtekening controleert nadat je de vervaldatum hebt gecontroleerd, kan een aanvaller een token maken met een toekomstige exp die de tijdscontrole doorstaat maar een ongeldige handtekening heeft.
Veilige validatiebestelling:
- Decodeer header (controleer algoritme)
- Handtekening verifiëren
- Controleer
exp(weigeren indien verlopen) - Controleer
nbf(afwijzen indien nog niet geldig) - Controleer
iat(afwijzen indien onredelijk oud) - Controleer de uitgever, doelgroep en andere claims
De meeste goed onderhouden bibliotheken gaan hier correct mee om, maar aangepaste middleware gaat vaak fout.
Bug #5: Tijdzoneverwarring in iat
JWT-tijdstempels zijn altijd UTC. Maar ontwikkelaars maken ze soms op basis van lokale tijd:
// FOUT — lokale tijdzone
const iat = new Date('2026-03-27T14:00:00').getTime() / 1000; // CORRECT — expliciete UTC
const iat = new Date('2026-03-27T14:00:00Z').getTime() / 1000;Zonder het achtervoegsel Z interpreteert JavaScript de tekenreeks in de lokale tijdzone, waardoor de tijdstempel uren kan verschuiven.
Bug #6: Tokens accepteren zonder nbf-controle
De claim nbf is handig voor tokens voor vertraagde activering, bijvoorbeeld een token dat alleen zou moeten werken na een geplande implementatie. Als uw validator nbf negeert, kunnen deze tokens worden gebruikt vóór de beoogde activeringstijd.
De meeste bibliotheken valideren nbf standaard, maar verifieer dit in uw configuratie, vooral met aangepaste middleware.
Bug #7: te lange vervaldatum
Het instellen van exp op 30 dagen voor een toegangstoken verslaat het doel van tokens met een korte levensduur. Beste praktijken:
- Toegangstokens: 5–15 minuten
- Vernieuw tokens: 7-30 dagen (met rotatie)
- ID-tokens: 1 uur
Voor veilige vernieuwingstokenpatronen raadpleegt u onze handleiding over JWT vernieuwingstokenrotatie.
Testcases die elke API zou moeten hebben
Voeg deze toe aan je testpakket om bugs in tijdclaims vroegtijdig op te sporen:
- Token met
expin het verleden → 401 - Token met
expprecies nu → 401 (grens) - Token zonder
exp→ 401 - Token met
nbfin de toekomst → 401 - Token met
nbfiets in de toekomst (binnen tolerantie) → 200 - Token met
iatin de toekomst → 401 (duidt op geknoei) - Token met tijdstempels in milliseconden → 401 (detecteert de ms/s-bug)
Veilige standaardinstellingen voor populaire frameworks
Node.js (jsonwebtoken)
jwt.sign(payload, geheim, { expiresIn: '15m' });
jwt.verify(token, geheim, { clockTolerance: 30, maxAge: '15m'
});Python (PyJWT)
jwt.decode(token, sleutel, algoritmen=['HS256'], speelruimte=tijddelta(seconden=30), opties={'require': ['exp', 'iat']})Ga (golang-jwt)
parser := jwt.NewParser( jwt.WithLeeway(30 * tijd.Seconde), jwt.WithValidMethods([]string{"HS256"}),
)Veelgestelde vragen
Moet dit verplicht zijn?
Hoewel de JWT-specificatie zegt dat iat optioneel is, helpt het verplicht stellen ervan bij het opsporen van fouten en audittrails. Zonder iat kunt u niet bepalen wanneer een token is gemaakt, waardoor het moeilijker wordt om te correleren met beveiligingsgebeurtenissen.
Hoeveel klokafwijking moet ik toestaan?
Een veel voorkomende veilige standaardwaarde is 30-60 seconden. Langer dan 2 minuten introduceert beveiligingsrisico's. Als uw systemen meer nodig hebben, corrigeer dan de NTP-synchronisatie in plaats van de scheefheidslimiet te vergroten.
Welke HTTP-statuscode moet ik retourneren voor een verlopen token?
Retourneer 401 Ongeautoriseerd met een duidelijke fouttekst zoals {"error": "token_expired"}. Retourneer niet 403 Verboden - dit impliceert dat het token geldig is maar geen machtigingen heeft, wat een andere situatie is.
Gerelateerde tools en artikelen
- JWT Decoder — inspecteer tijdclaims in elk token
- JWT-beveiligingsfouten — bredere JWT-valkuilen die verder gaan dan tijdclaims
- Tokenrotatie vernieuwen — veilig patroon voor langdurige sessies
- 2FA Gids — voeg een tweede laag toe naast tokens