Guide
Token JWT: come decodificare, verificare ed evitare gli errori comuni
Tre segmenti base64url, una firma che devi effettivamente verificare, e un bug storico — alg: none — che viene ancora distribuito in alcune librerie.
By Buğra SözeriPublished
Un JWT è tre stringhe codificate in base64url unite da punti. La prima è metadati, la seconda sono i dati che ti interessano davvero, e la terza è la firma che dimostra che le prime due non sono state modificate. La maggior parte dei bug JWT deriva dal trattare la terza parte come opzionale — o dal fraintendere ciò che il formato garantisce in primo luogo.
La struttura a tre segmenti
Un JWT ha questo aspetto:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNzQ4NjQ4MDAwfQ.qZdfL_HxR_eRT3z3qZX7Rqv0kK7r0sQYMfRBlLcM2hIDividi sui punti e ottieni intestazione, payload, firma. Ognuno dei primi due è un oggetto JSON che è stato codificato in base64url — una variante URL-safe di base64 che sostituisce + con -, / con _ e omette il padding. Incolla qualsiasi token nel nostro decoder JWT per vedere le tre parti inflate in JSON semplice.
L’intestazione
{
"alg": "HS256",
"typ": "JWT"
}Due campi. alg nomina l’algoritmo di firma; copriamo i valori di seguito. typ identifica il token come JWT. Alcuni token includono anche kid (ID chiave) in modo che il verificatore sappia quale chiave pubblica in un set di chiavi usare.
Il payload
{
"sub": "1234567890",
"iat": 1748648000,
"exp": 1748651600,
"iss": "https://auth.example.com",
"aud": "https://api.example.com"
}Qualsiasi oggetto JSON si scelga. I campi si chiamano claim. RFC 7519 definisce sette nomi di claim “registrati” che dovresti riutilizzare quando il loro significato corrisponde al tuo.
La firma
La firma viene calcolata su base64url(intestazione) + “.“ + base64url(payload) usando l’algoritmo e la chiave indicati dall’intestazione. La firma stessa è il terzo segmento codificato in base64url. È ciò che rende un JWT un JWT piuttosto che una semplice busta base64.
Le claim registrate
- iss (issuer). Chi ha coniato il token. Di solito un URL che identifica il tuo servizio di autenticazione. I verificatori devono controllare che corrisponda all’issuer atteso.
- sub (subject). Di chi è il token — tipicamente l’ID utente.
- aud (audience). Per chi è il token — l’URL API o il nome del servizio. Un verificatore che non corrisponde all’audience atteso deve rifiutare il token.
- exp (expiration). Unix timestamp dopo il quale il token non è valido. I verificatori devono rifiutare i token scaduti.
- nbf (not before). Unix timestamp prima del quale il token non è valido. Opzionale.
- iat (issued at). Unix timestamp quando il token è stato emesso. Informativo.
- jti (JWT ID). Un ID univoco per il token stesso, utile per la revoca esplicita o per prevenire il replay.
HS256 vs RS256 vs ES256
HS256 (HMAC-SHA-256, simmetrico)
La firma è un HMAC sull’intestazione e il payload codificati usando un segreto condiviso. Chiunque possa verificare la firma può anche creareuna nuova — la stessa chiave fa entrambi i lavori. Usa HS256 quando l’issuer e il verificatore sono la stessa parte. Non usare HS256 quando terze parti devono verificare i tuoi token.
RS256 (RSA-SHA-256, asimmetrico)
La firma è una firma RSA usando la chiave privata dell’issuer. I verificatori usano la chiave pubblica dell’issuer — pubblicata in un endpoint JWKS, tipicamente — per controllare la firma. I verificatori non possono coniare token. Questo è il default per l’identità federata: OpenID Connect, Auth0, Cognito, ogni flusso “login with X”.
ES256 (ECDSA su P-256, asimmetrico)
Stesso modello di sicurezza di RS256 ma con firme a curva ellittica. I vantaggi: dimensione della firma ~10× più piccola (64 byte vs 256), verifica più veloce e sicurezza più forte per bit. Lo svantaggio: le implementazioni ECDSA sono più facili da sbagliare rispetto a RSA, e storicamente hanno prodotto bug critici.
EdDSA (Ed25519)
Più recente di ES256, più difficile da usare male, il più veloce delle opzioni asimmetriche. Elencato in RFC 8037 come algoritmo JWT ma non universalmente supportato — controlla il tuo stack prima di adottarlo.
L’attacco alg: none
La specifica JWT definisce un valore speciale dell’algoritmo none che significa “non firmato.” Nel 2015, i ricercatori hanno dimostrato che diverse librerie JWT onoravano il campo alg nell’intestazione come istruzioni per la verifica. La mitigazione è verificare rispetto a un algoritmo atteso, non all’algoritmo che il token afferma:
// SBAGLIATO — si fida dell'intestazione
jwt.verify(token, key);
// GIUSTO — fissa l'algoritmo
jwt.verify(token, key, { algorithms: ["RS256"] });Altri errori comuni
Fidarsi dell’intestazione kid senza validazione
L’intestazione kid dice al verificatore quale chiave usare da un set di chiavi. Se usi kid ciecamente come percorso di file o chiave del database, un attaccante può fornire un valore malevolo. Tratta sempre kid come una chiave di ricerca opaca in un set noto, non come un percorso o una query.
Confusione di algoritmi (RS256 → HS256)
Alcune librerie accettano la chiave pubblica per la verifica RS256 ma la accettano anche come segreto HMAC per HS256. Fissa l’algoritmo.
Token di accesso a lunga durata senza revoca
I JWT sono stateless. Non puoi invalidare un token trapelato prima del suo exp senza mantenere una denylist lato server. Il pattern standard: token di accesso a breve durata (5-60 minuti) più refresh token a lunga durata memorizzato lato server.
Mettere segreti nel payload
Il payload è codificato in base64url, non crittografato. Chiunque abbia il token può leggere ogni claim. Non mettere password, chiavi API, dati personali soggetti a rigola regolamentazione, o qualsiasi altra cosa che non scriveresti in un log del server. Se hai bisogno di riservatezza, usa JWE.
Memorizzare i JWT in localStorage
localStorage è leggibile da qualsiasi JavaScript sulla tua origine, il che significa che qualsiasi XSS diventa un furto completo di token. Preferisci i cookie sicuri HTTP-only per i token memorizzati nel browser.
Quando JWT è lo strumento sbagliato
Per una web app di prima parte, una sessione regolare lato server con un cookie sicuro HTTP-only è più semplice:
- Immediatamente revocabile. Elimina la riga della sessione, l’utente è disconnesso.
- Più piccola in rete. Un ID di sessione è un cookie da 30 byte; un JWT può essere 500-2000 byte.
- Modello di sicurezza più semplice. Nessun bug di confusione degli algoritmi, nessun
alg: none, nessuna confusione sulla segretezza del payload.
JWT vale la sua complessità quando hai più servizi che devono fidarsi dell’identità utente senza tutti parlare a un store di sessioni centrale, o quando emetti token a terze parti — che è esattamente il ruolo che i JWT svolgono in un flusso OAuth 2.0 / OpenID Connect.
Il punto fermo onesto
Decodificare un JWT è banale — base64url, dividi, analizza il JSON. Il nostro decoder nel browser lo fa senza inviare il token da nessuna parte, il che conta perché i token spesso contengono claim identificativi che non vorresti incollare in un sito di terze parti.
Verificare un JWT è anche semplice, purché tu fissi l’algoritmo, validi iss, aud e exp, e non ti fidi mai dell’intestazione per dirti come verificare. Scegli HS256 se issuer e verificatore sono la stessa parte; scegli RS256 o ES256 con una libreria collaudata altrimenti. E prima di raggiungere un JWT, controlla se un semplice cookie di sessione farebbe.
Frequently asked questions
- Posso fidarmi di un JWT solo perché è stato decodificato?
- No — la decodifica fa solo il parse base64url dell’intestazione e del payload. Chiunque può decodificare un JWT; la proprietà di sicurezza deriva interamente dalla verifica della firma rispetto a una chiave di cui ti fidi. Chiama sempre verify(token, key), non decode(token), nei percorsi di codice in produzione.
- Un JWT è crittografato?
- Un JWT standard (tecnicamente un JWS) è firmato, non crittografato — il payload è leggibile da chiunque abbia il token. Se hai bisogno di riservatezza, usa invece un JWE (JSON Web Encryption). Non mettere mai password, chiavi API o altri segreti nel payload JWT assumendo che siano nascosti.
- Cos’è l’attacco alg: none?
- Le prime librerie JWT onoravano il campo alg nell’intestazione come istruzioni — incluso il valore speciale ‘none’, che significa ‘nessuna firma’. Un attaccante poteva cambiare l’algoritmo in none, eliminare il segmento della firma e presentare un token che la libreria accettava come valido. Le librerie moderne o rifiutano ‘none’ per impostazione predefinita o richiedono un opt-in esplicito.
- I token di accesso dovrebbero essere a breve o lunga durata?
- Breve — da minuti a un’ora al massimo. I JWT non possono essere revocati senza infrastruttura. Una vita breve del token di accesso combinata con un refresh token a lunga durata memorizzato lato server è il pattern standard: brevi finestre di esposizione se un token trapela, facile revoca invalidando il refresh token.
- Quando JWT è davvero la scelta sbagliata?
- Quando il client è una web app di prima parte e controlli entrambi i lati. Una sessione regolare lato server con un cookie sicuro HTTP-only è più semplice, immediatamente revocabile, più piccola in rete e immune alla maggior parte dei bug specifici JWT. JWT guadagna la sua complessità in scenari di terze parti genuini — identità federata, microservizi che devono fidarsi di un token senza chiamare un servizio auth centrale per ogni richiesta.
- Qual è la differenza tra iat e nbf?
- iat (emesso alle) è quando il token è stato creato — informativo, non un confine di validità. nbf (non prima) è il momento più presto in cui il token è valido — i verificatori devono rifiutare il token prima di nbf. exp (scadenza) è il momento più tardi in cui il token è valido. La maggior parte dei token imposta iat e exp; nbf è usato principalmente quando si emettono token che dovrebbero diventare validi in futuro.
Related
- Decoder JWTIncolla un token, vedi intestazione e payload — localmente, niente inviato da nessuna parte
- Glossario JWTRiferimento breve per il formato e le sue parti
- Glossario JWSJSON Web Signature — il contenitore firmato che la maggior parte dei JWT usa
- Glossario JWEJSON Web Encryption — quando hai davvero bisogno di riservatezza
- Glossario claim JWTiss, sub, exp, aud e il resto delle claim registrate
- Hashing crittografico spiegatoPezzo complementare per la discussione su HS256 vs RS256 vs ES256
Published May 31, 2026