Decoder JWT
Come funziona
Incolla un JWT, la lunga stringa xxx.yyy.zzz che trovi negli header Authorization: Bearer, nelle risposte OAuth, nei cookie o nei token di autenticazione di Firebase. Lo strumento la divide nelle sue tre parti (header, payload, firma), decodifica in Base64URL le prime due e le mostra come JSON formattato, ciascuna con il suo pulsante per copiarla. La firma non viene mostrata: è un valore binario, non un testo leggibile. Se la stringa non ha esattamente tre parti o non contiene JSON valido, compare l'avviso Token JWT non valido.
L'header dice quale algoritmo ha firmato il token (alg) e a volte quale chiave è stata usata (kid). I valori più comuni: HS256 (HMAC-SHA-256, simmetrico), RS256 (RSA-SHA-256, asimmetrico, il predefinito per OAuth e OpenID Connect), ES256 (ECDSA P-256, preferito da Apple e dagli emittenti più recenti) e il famigerato “none”, che vuol dire token non firmato e va sempre rifiutato.
Il payload contiene i claim, cioè i dati veri e propri del token. I claim standard da conoscere: • `iss`: issuer, il servizio che ha emesso il token • `sub`: subject, di solito l'ID dell'utente • `aud`: audience, il servizio autorizzato a usarlo • `exp`: scadenza, un timestamp Unix in secondi • `iat`: il momento dell'emissione • `nbf`: not before, il token non è valido prima di questo momento • `jti`: un ID univoco del token, usato per revocarlo singolarmente
Tutto il resto sono claim personalizzati (ruoli, permessi, ID del tenant, email). Il JSON mantiene l'ordine delle chiavi e i tipi originali, quindi vedi esattamente cosa emette il tuo server di autenticazione.
Scadenza a colpo d'occhio. Sopra l'header un'etichetta confronta `exp` con l'orologio del tuo dispositivo: Valido, non scaduto se la scadenza è nel futuro, Scaduto se è passata, Nessun claim exp se il token non ne ha uno. Per trasformare il valore di `exp` in una data leggibile c'è il convertitore di timestamp Unix di questo sito.
Un avviso da prendere sul serio: non incollare un JWT di produzione in uno strumento online che non controlli. I JWT possono contenere dati personali (email, ID utente), identificativi di sessione e permessi di accesso. Uno strumento che invia il token a un server lo ha appena ricevuto, e magari registrato. Questo strumento lo decodifica dentro la pagina, e puoi verificarlo nella scheda Rete degli strumenti per sviluppatori, ma per il debug in produzione, quando puoi, preferisci una CLI o un'estensione dell'editor in locale.
Domande frequenti
Come decodificare un token JWT?
- Incollalo nel campo in alto: header e payload compaiono subito sotto come JSON formattato. Un JWT è fatto di tre parti separate da punti, e le prime due sono JSON codificato in Base64URL, quindi basta decodificarle per leggerle. Non serve nessuna chiave: la chiave serve solo per verificare la firma.
È sicuro incollare qui il mio JWT?
- Più che nella maggior parte dei decoder online, perché questo gira interamente nel browser: incollare e decodificare non fa partire nessuna richiesta di rete, come puoi verificare nella scheda Rete degli strumenti per sviluppatori. Detto questo, per i token di produzione con una sessione attiva la strada più sicura resta una CLI locale o l'estensione JWT del tuo editor. Qualsiasi token valido incollato in una pagina web è a rischio se la pagina o un'estensione del browser sono compromesse.
Verifica la firma?
- No, questo strumento decodifica soltanto. Per verificare la firma serve il segreto condiviso (HS256) o la chiave pubblica dell'emittente (RS256, ES256), e nessuno dei due va messo in uno strumento web qualsiasi. Decodificare vuol dire solo leggere; la verifica è un passaggio separato, da fare lato server o con una libreria dedicata (jose, jsonwebtoken, pyjwt).
Come controllo se un JWT è scaduto?
- Guarda l'etichetta sopra l'header: Valido, non scaduto finché la scadenza è nel futuro, Scaduto quando è passata. Si basa sul claim `exp`, un timestamp Unix in secondi: il token è scaduto quando `exp` è minore di `Date.now() / 1000`. Se compare Nessun claim exp il token non scade mai, e di solito è un errore di configurazione, perché quasi tutti gli emittenti dovrebbero impostarlo.
Quali claim mostra?
- Tutti quelli presenti nel payload, nell'ordine originale: i claim registrati come iss (issuer), sub (subject), aud (audience), exp (scadenza), iat (emissione), nbf (not before) e jti (ID del token), e quelli personalizzati come ruoli, tenant, email o scope. I valori restano nel loro tipo JSON, quindi numeri e booleani non diventano stringhe.
Perché il mio token ha tre parti separate da punti?
- Perché un JWT ha esattamente tre parti: header.payload.firma, ognuna codificata in Base64URL. Header e payload sono JSON; la firma è un MAC o una firma binaria che non diventa testo leggibile. Se il tuo token ha più o meno punti non è un JWT standard, e lo strumento lo segnala come non valido: potrebbe essere un JWE (la variante cifrata), che qui non è supportata.
Il mio JWT ha "alg":"none": è pericoloso?
- Sì, è stata una vulnerabilità storica grave. alg:none vuol dire token non firmato, e un'applicazione che lo accetta senza controlli si fida di token falsificati. Le librerie moderne lo rifiutano per default. Trovarlo in un token di un servizio in produzione è un campanello d'allarme: l'emittente non dovrebbe mai produrre token non firmati.
Che differenza c'è tra HS256 e RS256?
- HS256 è simmetrico (HMAC con un segreto condiviso): veloce, ma chi può verificare può anche firmare. RS256 è asimmetrico (una coppia di chiavi RSA): l'emittente firma con la chiave privata e chi riceve verifica con quella pubblica. OAuth e OpenID Connect usano RS256 (o ES256) proprio perché la chiave pubblica si può distribuire senza rischi. Usa HS256 solo per token interni allo stesso servizio, dove un segreto condiviso ha senso.
Posso decodificare un JWT in Node, Python o da terminale?
- Sì, con una riga. Node: `Buffer.from(token.split('.')[1], 'base64url').toString()`. Python: `import base64,json; json.loads(base64.urlsafe_b64decode(token.split('.')[1] + '=='))`. Bash: `echo $TOKEN | cut -d. -f2 | base64 -d | jq` (aggiungi il padding `=` se serve). Tutti e tre decodificano solo il payload; per la verifica usa jose (Node), pyjwt (Python) o una CLI come jwt-cli.
Che differenza c'è tra JWT e JWE?
- Un JWT (JSON Web Token, RFC 7519) è firmato: il payload è codificato in Base64 e chiunque può leggerlo, perché la firma dimostra solo chi l'ha emesso. Un JWE (JSON Web Encryption, RFC 7516) è cifrato: il payload è illeggibile senza la chiave di decifratura. I JWT hanno tre parti, i JWE cinque (header.encryptedKey.iv.ciphertext.tag). Questo strumento decodifica solo i JWT; un JWE richiede la chiave privata del destinatario.
Algoritmi di firma JWT: quale usare e quando
Il campo `alg` nell'header di un JWT dice come è stato firmato il token. Un riepilogo degli algoritmi che incontrerai nei token di produzione.
| alg | Tipo | Chiavi | Uso tipico | Note |
|---|---|---|---|---|
| HS256 | HMAC-SHA-256 (simmetrico) | Segreto condiviso ≥ 32 byte | Token interni allo stesso servizio, app single-tenant | Veloce. Chi può verificare può anche firmare, quindi il segreto non va mai distribuito |
| HS384 | HMAC-SHA-384 (simmetrico) | Segreto condiviso ≥ 48 byte | Come HS256 con un hash più robusto | Raro. HS256 basta quasi sempre |
| HS512 | HMAC-SHA-512 (simmetrico) | Segreto condiviso ≥ 64 byte | Token simmetrici ad alta sicurezza | Raro |
| RS256 | RSA-PKCS1-v1_5 + SHA-256 | Coppia di chiavi RSA (almeno 2048 bit) | OAuth 2.0, OpenID Connect, API pubbliche | Predefinito per Auth0, Okta, AWS Cognito, Firebase. La chiave pubblica si condivide via JWKS |
| RS384 | RSA-PKCS1-v1_5 + SHA-384 | RSA 2048+ | Come RS256 con un hash più robusto | Poco diffuso |
| RS512 | RSA-PKCS1-v1_5 + SHA-512 | RSA 2048+ | Come RS256 con un hash più robusto | Poco diffuso |
| ES256 | ECDSA P-256 + SHA-256 | Coppia di chiavi EC P-256 | OAuth moderno, app mobili, Accedi con Apple | Firme più piccole (64 byte contro i 256+ di RSA). La scelta della maggior parte degli emittenti recenti |
| ES384 | ECDSA P-384 + SHA-384 | Coppia di chiavi EC P-384 | ECDSA ad alta sicurezza | Poco diffuso |
| ES512 | ECDSA P-521 + SHA-512 | Coppia di chiavi EC P-521 | ECDSA ad altissima sicurezza | Poco diffuso |
| EdDSA | Ed25519 (o Ed448) | Chiave Ed25519 da 32 byte | Alternativa più recente a ECDSA: veloce, a tempo costante | In crescita. Supportato da jose, jsonwebtoken (con plugin), pyjwt 2.6+ |
| PS256 | RSA-PSS + SHA-256 | RSA 2048+ | Padding RSA più sicuro di RS256 | Consigliato al posto di RS256 da alcune specifiche (FAPI). Controlla che la tua libreria lo supporti |
| none | (non firmato) | (nessuna) | Solo debug | Da non accettare MAI in produzione: vulnerabilità storica grave (CVE-2015-9235). Rifiutalo esplicitamente |
Definiti da RFC 7518 (JOSE / JWA). La maggior parte dei provider di identità usa RS256 per default; gli stack moderni (Apple, Firebase, le app Auth0 più recenti) usano sempre più spesso ES256 o EdDSA per token più piccoli e prestazioni migliori sui dispositivi mobili.