JWT exp/iat/nbf Errori: bug di time-claim che interrompono l'autenticazione
Le dichiarazioni temporali diJWT - exp, iat e nbf - sono ingannevolmente semplici. Sono solo timestamp Unix. Eppure causano alcuni dei bug di autenticazione più frustranti nella produzione: token che scadono troppo presto, token che funzionano su un server ma non su un altro e token che non scadono mai.
Questo articolo tratta i bug più comuni legati ai time-claim, il motivo per cui si verificano e come risolverli con impostazioni predefinite sicure.
Come funzionano exp, iat e nbf
Ogni JWT può trasportare tre richieste legate al tempo nel suo carico utile:
Tutti e tre sono date numeriche: il numero di secondi dal 1970-01-01T00:00:00Z (epoca Unix). Non millisecondi, secondi. Questa distinzione da sola causa circa il 20% di tutti i bug temporali JWT.
Utilizza il nostro Decodificatore JWT per controllare istantaneamente le dichiarazioni di tempo in qualsiasi token.
Bug n. 1: utilizzo dei millisecondi anziché dei secondi
JavaScript Date.now() restituisce millisecondi. Le specifiche JWT richiedono pochi secondi. Impostando exp su Date.now() + 3600000 crea un token che scade nell'anno 2089, non tra un'ora.
// SBAGLIATO — millisecondi
const exp = Date.now() + 3600000; // CORRETTO: secondi
const exp = Math.floor(Date.now() / 1000) + 3600;La maggior parte delle librerie JWT lo gestiscono internamente, ma se stai creando i payload manualmente, questa è la prima cosa da controllare.
Bug n. 2: richiesta di esperienza mancante completamente
Se dimentichi di impostare exp, molte biblioteche creeranno volentieri un token che non scade mai. Questo è un rischio per la sicurezza: un token trapelato rimane valido per sempre.
Imposta sempre exp. Convalidalo sempre sul server. Se la tua libreria non rifiuta i token senza exp per impostazione predefinita, configurala per farlo.
// Node.js jsonwebtoken: applica la scadenza
jwt.verify(token, segreto, { maxAge: '1h' });Bug n. 3: disallineamento dell'orologio tra i server
Il server A emette un token alle 14:00:00. L'orologio del server B segna 13:59:55 (5 secondi indietro). Se il token ha nbf: 1711540800 (14:00:00), il server B lo rifiuta come "non ancora valido".
Ciò è particolarmente comune in:
La soluzione
Consenti una piccola tolleranza orologio (chiamata anche "margine di manovra") - in genere 30-60 secondi:
// jsonwebtoken
jwt.verify(token, segreto, { clockTolerance: 30 }); // jose (Node.js)
attendono jwtVerify(token, chiave, { clockTolerance: '30s' });Non impostare mai una tolleranza superiore a 2 minuti. Se ne hai bisogno di più, correggi invece la sincronizzazione NTP.
Bug n. 4: ordine di convalida errato
L'ordine di convalida corretto è importante. Se controlli la firma dopo aver controllato la scadenza, un utente malintenzionato può creare un token con un futuro exp che supera il controllo temporale ma ha una firma non valida.
Ordine di convalida sicuro:
exp (rifiuta se scaduto)nbf (rifiuta se non ancora valido)iat (rifiuta se irragionevolmente vecchio)La maggior parte delle librerie ben gestite gestisce correttamente questo problema, ma il middleware personalizzato spesso sbaglia.
Bug n. 5: confusione sul fuso orario in iat
I timestamp diJWT sono sempre UTC. Ma gli sviluppatori a volte li creano utilizzando l'ora locale:
// SBAGLIATO: fuso orario locale
const iat = new Date('2026-03-27T14:00:00').getTime() / 1000; // CORRETTO: UTC esplicito
const iat = new Date('2026-03-27T14:00:00Z').getTime() / 1000;Senza il suffisso Z, JavaScript interpreta la stringa nel fuso orario locale, che può spostare il timestamp di ore.
Bug n. 6: accettazione di token senza controllo nbf
L'attestazione nbf è utile per i token ad attivazione ritardata, ad esempio un token che dovrebbe funzionare solo dopo una distribuzione pianificata. Se il tuo validatore ignora nbf, questi token possono essere utilizzati prima del tempo di attivazione previsto.
La maggior parte delle librerie convalida nbf per impostazione predefinita, ma verificalo nella configurazione, in particolare con il middleware personalizzato.
Bug n. 7: scadenza eccessivamente lunga
Impostare exp su 30 giorni per un token di accesso vanifica lo scopo dei token di breve durata. Migliori pratiche:
Per modelli di token di aggiornamento sicuri, consulta la nostra guida su JWT rotazione dei token di aggiornamento.
Casi di test che ogni API dovrebbe avere
Aggiungili alla tua suite di test per individuare tempestivamente i bug relativi alle richieste di tempo:
exp nel passato → 401exp esattamente adesso → 401 (confine)exp → 401nbf in futuro → 401nbf leggermente nel futuro (entro la tolleranza) → 200iat nel futuro → 401 (indica manomissione)Impostazioni predefinite sicure per i framework più diffusi
Node.js (jsonwebtoken)
jwt.sign(carico utile, segreto, { expiresIn: '15m' });
jwt.verify(token, segreto, { clockTolerance: 30, maxAge: '15m'
});Pitone (PyJWT)
jwt.decode(token, chiave, algoritmi=['HS256'], scarto=timedelta(secondi=30), opzioni={'require': ['exp', 'iat']})Vai (golang-jwt)
parser := jwt.NewParser( jwt.WithLeeway(30 * tempo.Secondo), jwt.WithValidMethods([]string{"HS256"}),
) FAQ
Dovrebbe essere obbligatorio?
Mentre le specifiche JWT dicono che iat è facoltativo, renderlo obbligatorio aiuta con il debug e gli audit trail. Senza iat, non è possibile determinare quando è stato creato un token, rendendo più difficile la correlazione con gli eventi di sicurezza.
Quanto spostamento dell'orologio devo consentire?
Un valore predefinito comune e sicuro è 30-60 secondi. Più di 2 minuti comportano rischi per la sicurezza. Se i tuoi sistemi necessitano di più, correggi la sincronizzazione NTP invece di ampliare il limite di distorsione.
Quale codice di stato HTTP devo restituire per un token scaduto?
Restituisci 401 Non autorizzato con un corpo dell'errore chiaro come {"error": "token_expired"}. Non restituire 403 Forbidden: ciò implica che il token è valido ma non dispone di autorizzazioni, il che è una situazione diversa.
Strumenti e articoli correlati
Decodificatore JWT: controlla le dichiarazioni di tempo in qualsiasi token Errori di sicurezza JWT: insidie JWT più ampie oltre le affermazioni temporali Aggiorna rotazione token: modello sicuro per sessioni di lunga durata Guida 2FA: aggiungi un secondo livello oltre i token