[ Înapoi la blog

Greșeli exp/iat/nbf JWT: erori de revendicare în timp care încalcă autentificarea

[Securitatea dezvoltatorului27 martie 2026·8 minute de citire] [JWT time claims debugging

Revendicările de timp JWT — exp, [ și nbf — sunt înșelător de simple. Sunt doar marcaje temporale Unix. Cu toate acestea, provoacă unele dintre cele mai frustrante erori de autentificare din producție: token-uri care expiră prea devreme, token-uri care funcționează pe un server, dar nu pe altul și token-uri care nu expiră deloc.

Acest articol acoperă cele mai frecvente erori de revendicare a timpului, de ce apar și cum să le remediați cu valori implicite sigure.

[ funcționează exp, iat și nbf

Fiecare JWT poate include trei revendicări legate de timp în sarcina sa utilă:

[
  • exp (Timp de expirare) — simbolul NU TREBUIE acceptat după acest marcaj temporal
  • iat (Emis la) — când a fost creat jetonul
  • nbf (Nu înainte) — simbolul NU TREBUIE acceptat înainte de acest marcaj temporal
  • [

    Toate trei sunt date numerice: numărul de secunde de la 1970-01-01T00:00:00Z (epoca Unix). Nu milisecunde - secunde. Numai această distincție cauzează aproximativ 20% din toate erorile de timp JWT.

    Utilizați Decodorul nostru JWT pentru a inspecta instantaneu revendicările de timp în orice simbol.

    Eroarea #1: Folosirea milisecundelor în loc de secunde

    JavaScript Date.now() returnează milisecunde. Specificația JWT necesită secunde. Setarea [ la Date.now() + 3600000 creează un token care expiră în anul 2089, nu într-o oră.

    [// GREȘIT — milisecunde const exp = Date.now() + 3600000; // CORECT — secunde const exp = Math.floor(Date.now() / 1000) + 3600;

    Majoritatea bibliotecilor JWT se ocupă de acest lucru intern, dar dacă construiți încărcături utile manual, acesta este primul lucru de verificat.

    Eroarea nr. 2: Lipsește o revendicare completă a exp.[

    Dacă uitați să setați exp, multe biblioteci vor crea cu plăcere un simbol care nu expiră niciodată. Acesta este un risc de securitate: un token scurs rămâne valabil pentru totdeauna.

    [ întotdeauna [. Validați-l întotdeauna pe server. Dacă biblioteca dvs. nu respinge jetoanele fără exp în mod implicit, configurați-o să facă acest lucru.

    // Node.js jsonwebtoken — impune expirarea
    jwt.verify(token, secret, [

    Bug #3: Clock Skew Between Servers

    [ A emite un token la 14:00:00. Ceasul serverului B arată 13:59:55 (cu 5 secunde în urmă). Dacă jetonul are nbf: 1711540800 (14:00:00), Serverul B îl respinge ca „nu este încă valid.”

    [ lucru este obișnuit în special în:

    [ [ de microservicii cu ceasuri nesincronizate
  • Funcții fără server în care containerele au deplasare a ceasului
  • Aplicații mobile în care ceasul dispozitivului este setat manual
  • [ [

    Permiteți o toleranță mică de ceas (numită și „leeway”) — de obicei 30–60 de secunde:

    [// jsonwebtoken jwt.verify(token, secret, [ // jose (Node.js) așteaptă jwtVerify(indicativ, cheie, [ [ setați niciodată toleranța peste 2 minute. Dacă aveți nevoie de mai multe, remediați sincronizarea NTP.

    Eroarea #4: Comanda de validare greșită

    [ corectă de validare contează. Dacă verificați semnătura după verificarea expirării, un atacator poate crea un jeton cu un viitor exp care trece de verificarea timpului, dar are o semnătură nevalidă.

    [ de validare sigură:

    [ [ antetul (algoritm de verificare) [ semnătura [ exp (respingeți dacă a expirat)
  • Verificați nbf (respingeți dacă nu este încă valid)
  • Verificați iat (respingeți dacă este nerezonabil de vechi)
  • Verificați emitentul, publicul și alte afirmații
  • [

    Majoritatea bibliotecilor bine întreținute gestionează acest lucru corect, dar middleware-ul personalizat greșește adesea.

    [ #5: Confuzia fusului orar în iat [ de timp JWT sunt întotdeauna UTC. Dar dezvoltatorii le creează uneori folosind ora locală:

    // GREȘIT — fus orar local
    const iat = new Date('2026-03-27T14:00:00').getTime() / 1000; // CORECT — UTC explicit
    const iat = new Date('2026-03-27T14:00:00Z').getTime() / 1000;

    Fără sufixul Z, JavaScript interpretează șirul în fusul orar local, care poate schimba marcajul de timp în funcție de ore.

    [ #6: Acceptarea jetoanelor fără verificare nbf

    Revendicarea nbf este utilă pentru token-urile de activare întârziată — de exemplu, un token care ar trebui să funcționeze numai după o implementare programată. Dacă validatorul dvs. ignoră nbf, aceste jetoane pot fi folosite înainte de momentul de activare prevăzut.

    Majoritatea bibliotecilor validează nbf în mod implicit, dar verifică acest lucru în configurarea ta, în special cu middleware personalizat.

    [ #7: Expirare prea lungă

    Setarea exp la 30 de zile pentru un jeton de acces înfrânge scopul jetonelor de scurtă durată. Cele mai bune practici:

    [ [Jetoane de acces: 5–15 minute
  • Refresh tokens: 7–30 days (with rotation)
  • [Jetoane ID: 1 oră [

    Pentru modele sigure de jetoane de reîmprospătare, consultați ghidul nostru despre Rotația jetoanelor de reîmprospătare JWT.

    Cazuri de testare pe care ar trebui să le aibă fiecare API

    Adăugați-le la suita dvs. de teste pentru a detecta erorile de revendicare a timpului mai devreme:

    [
  • Jeton cu exp în trecut → 401
  • Jeton cu exp exact acum → 401 (limită)
  • [ fără [ → 401
  • Jeton cu nbf în viitor → 401
  • Jeton cu nbf puțin în viitor (în limita toleranței) → 200
  • Jeton cu iat în viitor → 401 (indică modificarea)
  • Jeton cu marcaje de timp în milisecunde → 401 (detectează eroarea ms/s)
  • [ [ implicite sigure pentru cadrele populare [ (jsonwebtoken) [jwt.sign(sarcină utilă, secret, [ jwt.verify(token, secret, [ [ (PyJWT) [jwt.decode(token, cheie, algoritmi=['HS256'], leeway=timedelta(secunde=30), opțiuni=[ [ (golang-jwt) [parser := jwt.NewParser( jwt.WithLeeway(30 * time.Second), jwt.WithValidMethods([]string{"HS256"}), )[ [ [ frecvente [ trebui să fie obligatoriu?

    În timp ce specificația JWT spune că iat este opțional, făcându-l obligatoriu ajutoare pentru depanare și urmărire de audit. Fără [, nu puteți determina când a fost creat un token, ceea ce face mai dificilă corelarea cu evenimentele de securitate.

    Câtă înclinare a ceasului ar trebui să permit?

    O valoare implicită de siguranță obișnuită este 30-60 de secunde. Mai mult de 2 minute introduce riscul de securitate. Dacă sistemele dvs. au nevoie de mai multe, remediați sincronizarea NTP în loc să extindeți permisiunea de deformare.

    Ce cod de stare HTTP ar trebui să returnez pentru un token expirat?

    Return 401 Neautorizat cu un corp de eroare clar, cum ar fi {"error": "token_expired"}. Nu returnați 403 Forbidden — ceea ce înseamnă că simbolul este valid, dar nu are permisiuni, ceea ce este o situație diferită.

    [ [ și articole înrudite [
  • Decodor JWT — inspectează revendicările de timp în orice simbol
  • Greșeli de securitate JWT — capcane mai ample JWT dincolo de pretențiile de timp
  • Reîmprospătare rotație token — model sigur pentru sesiuni de lungă durată
  • Ghid 2FA — adăugați un al doilea strat dincolo de jetoane
  • [