Cos'è il JSON Web Token (JWT)?
Acquisisci una chiara comprensione dei fondamenti di JSON Web Token (JWT) in 5 minuti.
Il JSON Web Token (JWT) è ampiamente utilizzato nelle applicazioni web moderne e negli standard aperti come OpenID Connect, facilitando l'autenticazione e l'autorizzazione. Mentre l'ufficiale RFC 7519 serve come riferimento essenziale, può essere difficile da capire per i principianti. In questo articolo, ci concentreremo sui concetti fondamentali del JWT e li presenteremo in un linguaggio semplice con esempi.
Perché abbiamo bisogno di JWT?
Oggi è abbastanza comune utilizzare JSON per scambiare dati tra due parti. Considera un oggetto JSON che rappresenta un utente:
sub
è l'abbreviazione di "soggetto", che è un reclamo standard in OpenID Connect per rappresentare l'identificatore dell'utente (ID utente).
Come possiamo garantire l'integrità di questo oggetto JSON? In altre parole, come possiamo assicurarci che i dati non vengano alterati durante la trasmissione? Una soluzione comune è l'uso di firme digitali. Ad esempio, possiamo utilizzare la crittografia a chiave pubblica: il server firma l'oggetto JSON con la sua chiave privata, e il cliente può verificare la firma con la chiave pubblica del server.
In poche parole, il JWT offre un approccio standardizzato alla rappresentazione dell'oggetto JSON e della sua firma.
Il formato di JWT
Poiché ci sono molti algoritmi per creare firme digitali, è necessario specificare l'algoritmo utilizzato per la firma del JWT. Questo è realizzato costruendo un oggetto JSON:
alg
è l'abbreviazione di "algoritmo", etyp
è l'abbreviazione di "tipo".
Tipicamente, typ
è impostato su JWT
in maiuscolo. Per il nostro esempio, alg
è HS256
, che sta per HMAC-SHA256 (lo spiegheremo presto), e indica che stiamo utilizzando questo algoritmo per creare la firma.
Ora, abbiamo tutti gli ingredienti per un JWT:
- Intestazione JSON: Algoritmo e tipo
- Payload JSON: I dati effettivi
- Firma: La firma che include l'intestazione e il payload
Tuttavia, certi caratteri come spazi e interruzioni di linea non sono amichevoli per la trasmissione di rete. Pertanto, l'intestazione e il payload devono essere codificati in Base64URL. Il tipico JWT appare così:
Il
.
serve come delimitatore.
Mettiamo tutto insieme e creiamo un JWT:
Intestazione
JSON: {"alg":"HS256","typ":"JWT"}
Codificato in Base64URL: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload
JSON: {"sub":"foo","name":"John Doe"}
Codificato in Base64URL: eyJzdWIiOiJmb28iLCJuYW1lIjoiSm9obiBEb2UifQ
Firma
In HMAC-SHA256, la firma è creata con un segreto:
Ad esempio, con il segreto come some-great-secret
, la firma diventa: XM-XSs2Lmp76IcTQ7tVdFcZzN4W_WcoKMNANp925Q9g
.
JWT
Il JWT finale è:
Questo JWT valido può essere verificato da qualsiasi parte in possesso del segreto.
Scegli l'algoritmo di firma
Come accennato in precedenza, esistono vari algoritmi per creare firme digitali. Abbiamo utilizzato HS256
come esempio, ma potrebbe non essere abbastanza forte poiché il segreto deve essere condiviso tra le parti (ad es. il cliente e il server).
Negli scenari reali, i clienti possono includere applicazioni pubbliche come le app React che non possono mantenere il segreto al sicuro. Di conseguenza, l'approccio preferito prevede l'utilizzo della crittografia a chiave pubblica (cioè crittografia asimmetrica) per firmare il JWT. Iniziamo con l'algoritmo più popolare: RSA.
RSA
RSA, un algoritmo asimmetrico, utilizza una coppia di chiavi: una chiave pubblica e una chiave privata. La chiave pubblica è usata per verificare la firma, mentre la chiave privata è usata per la firma.
L'intestazione JSON per RSA appare così:
RS256
sta per RSA-SHA256, il che significa che la firma è creata con l'algoritmo RSA e la funzione hash SHA256. Puoi anche usareRS384
eRS512
per creare firme con le funzioni hash SHA384 e SHA512, rispettivamente.
La firma è creata con la chiave privata:
Ancora una volta, possiamo assemblare queste parti per creare un JWT, e il JWT finale appare così:
Ora, il cliente può verificare la firma senza conoscere la chiave privata.
ECDSA
Sebbene RSA sia ampiamente adottato, soffre di dimensioni di firma più grandi, a volte superando la dimensione combinata dell'intestazione e del payload. L'Elliptic Curve Digital Signature Algorithm (ECDSA) è un altro algoritmo asimmetrico che può creare firme più compatte ed è più performante.
Per generare una chiave privata per ECDSA, dobbiamo scegliere una curva. Questo è fuori dall'ambito di questo articolo, ma puoi trovare più informazioni qui.
L'intestazione JSON per ECDSA appare così:
ES256
sta per ECDSA-SHA256, il che significa che la firma è creata con l'algoritmo ECDSA e la funzione hash SHA256. Puoi anche usareES384
eES512
per creare firme con le funzioni hash SHA384 e SHA512, rispettivamente.
La firma è creata con la chiave privata:
Il JWT finale conserva la stessa struttura di RSA ma con una firma significativamente più corta:
Verifica il JWT
Verificare un JWT è semplice come il processo inverso di creazione di un JWT:
- Dividi il JWT in tre parti (intestazione, payload e firma) utilizzando il delimitatore
.
. - Decodifica l'intestazione e il payload con Base64URL.
- Verifica la firma con l'algoritmo specificato nell'intestazione e la chiave pubblica (per algoritmi asimmetrici).
Ci sono molte librerie che sono disponibili per assistere con la verifica di JWT, come jose per Node.js e i browser web.
Conclusione
In questo articolo, abbiamo brevemente spiegato i concetti base di JWT, insieme alla panoramica su come crearlo e verificarlo. Molti dettagli restano inesplorati, e li copriremo in articoli futuri.
Logto sfrutta standard aperti come JWT e OpenID Connect per proteggere le tue app e API con flussi di lavoro semplificati per ogni sviluppatore. Se sei interessato, puoi provarlo gratuitamente (non è richiesta la carta di credito).