ToolDeck

JWT

2 strumenti

Fondamentali della sicurezza Web

La sicurezza Web è la pratica di proteggere le applicazioni Web e le API da accessi non autorizzati, violazioni dei dati e attacchi. Le applicazioni moderne usano autenticazione (verificare chi sei), autorizzazione (verificare cosa puoi fare) e crittografia per definire i confini di sicurezza.

I JSON Web Token (JWT) sono il meccanismo di autenticazione stateless dominante nello sviluppo Web moderno. Comprendere come funzionano i JWT — inclusa la loro struttura, gli algoritmi di firma e le vulnerabilità — è essenziale per costruire API e applicazioni sicure. Grazie alla loro natura compatta e autocontenuta, i JWT si sono affermati come standard de facto in OAuth2 e OpenID Connect.

JSON Web Tokens (JWT)

Un JWT è un modo compatto e sicuro per URL di rappresentare claim tra due parti. È composto da tre parti codificate in Base64url separate da punti. I JWT possono essere verificati senza interrogazioni al database perché la firma copre l'intero token: ciò li rende ideali per architetture distribuite e microservizi dove più servizi devono convalidare le identità in modo indipendente.

Le tre parti di un JWT

Header

Contiene metadati sul token: l'algoritmo di firma (alg) e il tipo di token (typ). È sempre JSON codificato in Base64url. La scelta dell'algoritmo nell'intestazione influisce sulla sicurezza dell'intero token.

Codificato
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Decodificato
{
  "alg": "HS256",
  "typ": "JWT"
}
Payload

Contiene i claim: dichiarazioni sull'utente e metadati aggiuntivi. Anche questo è JSON codificato in Base64url. I dati del payload NON sono crittografati, solo firmati. Chiunque intercetti il token può decodificare e leggere il payload senza alcuna chiave.

Codificato
eyJzdWIiOiJ1c2VyXzEyMyIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcxNzIwMDAwMH0
Decodificato
{
  "sub": "user_123",
  "role": "admin",
  "exp": 1717200000
}
Signature

Una firma crittografica sull'intestazione e il payload codificati. La verifica garantisce che il token non sia stato manomesso. La chiave segreta (HMAC) o la chiave privata (RSA/ECDSA) non è mai inclusa nel token e non deve mai essere distribuita a parti non fidate.

Codificato
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Decodificato
HMACSHA256(
  base64url(header) + "." +
  base64url(payload),
  secret
)

Claim JWT standard

La specifica JWT definisce nomi di claim standard per garantire l'interoperabilità tra diverse librerie e servizi. Oltre ai claim standard, è possibile aggiungere claim personalizzati (private claims) per includere informazioni specifiche dell'applicazione, come i ruoli dell'utente o i permessi.

ClaimNomeDescrizione
issIssuerIdentifica il principal che ha emesso il token (es. URL del server di autenticazione)
subSubjectIdentifica il principal che è il soggetto del token (es. ID utente)
audAudienceIdentifica i destinatari per cui il token è destinato (es. URL della tua API)
expExpirationTimestamp Unix dopo il quale il token non deve essere accettato
nbfNot BeforeTimestamp Unix prima del quale il token non deve essere accettato
iatIssued AtTimestamp Unix in cui il token è stato emesso — usato per determinarne l'età
jtiJWT IDIdentificatore univoco del token, usato per prevenire attacchi di replay

Algoritmi di firma

L'algoritmo di firma è dichiarato nell'intestazione JWT. La scelta corretta è fondamentale per la sicurezza. Gli algoritmi asimmetrici come RS256 ed ES256 sono generalmente preferiti in produzione perché separano la capacità di emettere token da quella di verificarli: il server di autenticazione mantiene la chiave privata, mentre i servizi che consumano i token verificano usando solo la chiave pubblica.

HS256 / HS384 / HS512Simmetrico (HMAC)

Usa una chiave segreta condivisa per la firma e la verifica. Semplice da implementare, ma richiede che tutti i verificatori conoscano il segreto.

Usa quando: Servizi interni dove si controllano tutte le parti. Non usare mai quando terze parti devono verificare i token.
RS256 / RS384 / RS512Asimmetrico (RSA)

Usa una chiave privata per firmare e una pubblica per verificare. La chiave privata non lascia mai il server di autenticazione. Le chiavi pubbliche possono essere distribuite liberamente tramite un endpoint JWKS.

Usa quando: Architetture a microservizi, verifica token di terze parti, OAuth2 e OpenID Connect.
ES256 / ES384 / ES512Asimmetrico (ECDSA)

Come RSA ma con chiavi più piccole e firma più veloce. Offre sicurezza equivalente con prestazioni migliori.

Usa quando: Applicazioni mobile e IoT dove le prestazioni contano. Alternativa moderna a RSA.
"alg": "none"Non firmato — PERICOLOSO

Nessuna firma. Un token con alg:none non ha garanzie di integrità e può essere falsificato da chiunque.

Usa quando: Non usare mai in produzione. Alcune librerie JWT storicamente accettavano alg:none, portando a vulnerabilità critiche.

Flussi di autenticazione

Concessione password (diretta)
  1. 1.L'utente invia nome utente e password all'endpoint di login
  2. 2.Il server valida le credenziali contro il database utenti
  3. 3.Il server firma un JWT con i claim dell'utente e la scadenza
  4. 4.Il client memorizza il JWT (localStorage, cookie o memoria)
  5. 5.Il client invia il JWT nell'intestazione Authorization: Bearer per le richieste successive
Codice di autorizzazione + PKCE (OAuth2)
  1. 1.Il client reindirizza l'utente al server di autorizzazione con la sfida del codice
  2. 2.L'utente si autentica e autorizza l'applicazione client
  3. 3.Il server di autenticazione reindirizza con un codice di autorizzazione monouso
  4. 4.Il client scambia codice + verificatore per token di accesso e aggiornamento
  5. 5.Il client usa il token di accesso per le chiamate API; il token di aggiornamento per il rinnovo

Vulnerabilità JWT comuni

I JWT sono sicuri quando implementati correttamente. Questi sono gli errori di implementazione più comuni che portano a vulnerabilità di sicurezza. La maggior parte degli attacchi noti non sfrutta debolezze crittografiche, ma errori nella logica di validazione lato server: per questo è fondamentale usare librerie aggiornate e configurarle esplicitamente.

Confusione dell'algoritmo (alg:none)Critico

Alcune librerie accettano token con alg:none (nessuna firma). Un attaccante può modificare il payload e impostare alg su none per falsificare qualsiasi JWT. Specifica e valida sempre esplicitamente l'algoritmo consentito.

Confusione HS256/RS256Critico

Se una libreria deve verificare RS256 ma accetta HS256, un attaccante può firmare un token usando la chiave pubblica come segreto HMAC. La libreria lo verifica con successo. Fissa sempre l'algoritmo atteso nella configurazione della libreria.

Validazione della scadenza mancanteAlto

Un JWT senza claim exp, o codice che non controlla exp, permette l'uso indefinito dei token anche dopo che un utente si è disconnesso o è stato disabilitato. Imposta sempre brevi tempi di scadenza e verifica il claim exp ad ogni richiesta.

Dati sensibili nel payloadAlto

I payload JWT sono codificati in Base64, non crittografati. Chiunque intercetti un JWT può decodificare e leggere il payload. Non memorizzare mai password, numeri di carta di credito o altri segreti nei claim JWT. Se è necessario trasmettere dati sensibili nel token, utilizzare JWE (JSON Web Encryption).

Chiavi segrete deboli (HS256)Medio

I JWT firmati con HMAC con segreti brevi o prevedibili possono essere violati offline con forza bruta. Un attaccante che ottiene un JWT può provare miliardi di chiavi al secondo. Usa segreti casuali crittograficamente sicuri di almeno 256 bit.

Verifica della firma mancanteMedio

Accettare JWT senza verificare la firma si fida completamente del payload. Questo è un bug critico che consente a qualsiasi utente di creare claim arbitrari. Verifica sempre la firma prima di fidarti di qualsiasi claim.

Domande frequenti

I JWT sono crittografati?

I JWT standard (JWS — JSON Web Signature) sono firmati ma NON crittografati. Il payload è codificato in Base64url, facilmente reversibile. Chiunque ottenga un JWT può leggerne il contenuto. JWE (JSON Web Encryption) fornisce crittografia reale, ma è molto meno comune e aggiunge complessità operativa.

Quanto tempo deve essere valido un JWT?

I token di accesso dovrebbero essere di breve durata: da 5 a 60 minuti è tipico. I token di lunga durata sono pericolosi perché non possono essere revocati senza una lista di blocco. Usa token di aggiornamento (a lunga durata, memorizzati in modo sicuro) per ottenere nuovi token di accesso. In contesti ad alta sicurezza, come operazioni finanziarie o accesso a dati sensibili, considera token di accesso con validità di soli 5-15 minuti.

Dove memorizzare i JWT nel browser?

I cookie HttpOnly sono l'opzione più sicura — inaccessibili a JavaScript, prevenendo il furto tramite XSS. localStorage è vulnerabile agli attacchi XSS ma evita il CSRF. La memoria (variabile JavaScript) è la più sicura ma non sopravvive al refresh della pagina. Non esiste un'opzione perfetta: la scelta dipende dal modello di minaccia dell'applicazione e dall'uso combinato di misure di mitigazione come Content Security Policy.

Posso revocare un JWT prima della scadenza?

Non senza stato lato server. La natura stateless dei JWT significa che il server non può invalidarli. Soluzioni: brevi tempi di scadenza, una lista di blocco dei token (Redis), token di aggiornamento rotanti, oppure passare a token di sessione opachi per operazioni sensibili. Una lista di blocco basata sul claim jti (JWT ID) consente la revoca precisa di singoli token senza invalidare l'intera sessione utente.

Qual è la differenza tra JWT e cookie di sessione?

I cookie di sessione memorizzano un ID di sessione casuale; il server cerca i dati di sessione nel database o nella cache. I JWT sono autonomi — il server valida la firma senza query al database. I JWT scalano meglio su più server ma non possono essere revocati senza infrastrutture aggiuntive. I cookie di sessione sono più semplici da revocare ma richiedono storage condiviso in ambienti distribuiti.

Quali claim includere in un JWT?

Il minimo: sub (ID utente), exp (scadenza) e iat (emesso il). Aggiungi iss (issuer) per configurazioni multi-servizio e aud (audience) per limitare l'uso del token a specifici servizi. Mantieni i payload piccoli — i JWT vengono inviati con ogni richiesta. Non includere dati sensibili né oggetti profilo di grandi dimensioni.

RS256 è migliore di HS256?

RS256 (asimmetrico) è migliore per la maggior parte dei sistemi di produzione perché solo il server di autenticazione ha bisogno della chiave privata. Più servizi possono verificare i token usando la chiave pubblica senza condividere un segreto. HS256 è più semplice ma richiede che tutti i verificatori conoscano il segreto condiviso, aumentando la superficie di attacco in architetture con molti servizi.

Cos'è PKCE e perché è importante?

PKCE (Proof Key for Code Exchange) è un'estensione del flusso di codice di autorizzazione OAuth2 che previene gli attacchi di intercettazione del codice. È obbligatorio per i client pubblici (SPA, app mobile) che non possono memorizzare in modo sicuro un client secret. Funziona generando una coppia di valori casuali — code verifier e code challenge — che legano la richiesta di autorizzazione allo scambio del token, rendendo inutilizzabile un codice intercettato.