Introduzione a JSON Web Token (JWT)

Per lungo tempo sono stati utilizzati i cookie per l’autenticazione degli utenti sul web. Ancora oggi, questo metodo funziona molto bene, soprattutto per quanto riguarda certe applicazioni. Ma a volte è necessaria una maggiore flessibilità. Qui entra in gioco JSON Web Token. Il nuovo standard aperto è adottato sempre più di frequente dai principali siti web e applicazioni. In questo articolo vi mostriamo cos’è JWT, come funziona e dove viene applicato.

Cos’è un JSON Web Token?

Un JSON Web Token è un token di accesso standardizzato secondo RFC 7519 e consente lo scambio sicuro di dati tra due parti. Contiene tutte le informazioni importanti su un’entità, in modo che non sia necessaria alcuna interrogazione del database e che la sessione non debba essere memorizzata sul server (stateless session).

I JSON Web Token sono quindi particolarmente popolari nei processi di autenticazione. I brevi messaggi possono essere criptati e quindi fornire informazioni sicure su chi è il mittente e se lo stesso sia dotato dei permessi di accesso necessari. Gli utenti stessi entrano in contatto con il token solo indirettamente, ad esempio inserendo il proprio nome utente e la password in una maschera. La comunicazione effettiva avviene tra le varie applicazioni lato client e server.

Struttura di un JSON Web Token

Un JWT firmato è composto da tre parti, ciascuna codificata con Base64 e separata da un punto:

HEADER.PAYLOAD.SIGNATURE

Cosa significano queste tre parti? Di seguito ve le illustriamo singolarmente.

Header

L’header è composto da due parti e fornisce importanti informazioni sul token. Contiene il tipo di token e l’algoritmo di firma e/o crittografia utilizzato. Un esempio di header JWT può essere il seguente:

{ "alg": "HS256", "typ": "JWT" }

Il tipo raccomandato è sempre JWT. Descrive il tipo di supporto IANA "application/jwt". Nell’esempio sopra riportato, l’intestazione specifica che HMAC-SHA256, abbreviato in "HS256", viene utilizzato per firmare il token. Ulteriori metodi di cifratura tipici sono RSA con SHA-256 ("RS256") ed ECDSA con SHA-256 ("ES256"). Si sconsiglia l’uso della crittografia. Tuttavia, se i dati non hanno un elevato fattore di protezione, può essere specificato "none" come cifratura. I valori possibili sono standardizzati da JSON Web Encryption (JWE) secondo RFC 7516.

Per i JSON Web Token più complessi, firmati o criptati, c’è un parametro aggiuntivo "cty" per "content type". Può essere riempito anche con il valore "JWT". In tutti gli altri casi, questo parametro viene omesso.

Payload

La sezione Payload del JSON Web Token è la posizione che contiene le informazioni effettive che devono essere inviate all’applicazione. Qui si definiscono alcuni standard che specificano cosa e come si trasmettono determinati dati. Le informazioni sono fornite come coppie key/value, dove le chiavi in JWT sono chiamate claim. Ci sono tre diversi tipi di claim:

  • claim registrati all’interno del IANA JSON Web Token Claim Register e il cui scopo è definito in uno standard. Alcuni esempi sono l’emittente del token ("iss" per issuer), il dominio di destinazione ("aud" per audience) e il tempo di scadenza ("exp" per expiration time). Per mantenere la lunghezza del token il più breve possibile, sono stati utilizzati nomi di claim brevi.
  • Claim pubblici, definibili a proprio piacimento senza restrizione. Per evitare collisioni nella semantica delle keys, è necessario registrare pubblicamente i claim nel relativo registro dei claim dei JSON Web Token IANA o assegnare nomi resistenti alle collisioni.
  • Claim privati sono pensati per informazioni da scambiare specificatamente con la propria applicazione. Mentre i claim pubblici contengono informazioni come "name" o "e-mail", quelli privati sono più specifici. Un’informazione tipica è un "ID utente" o uno specifico "nome del reparto". È importante assicurarsi che il nome non si scontri con i claim registrati o pubblici.

Tutti i claim sono facoltativi, pertanto non è necessario utilizzare ciascun claim registrato. In generale, i payload utili possono contenere qualsiasi numero di claim, ma è consigliabile limitare le informazioni nel JWT allo stretto necessario. Più grande è il JWT, più risorse richiede per la (de)codifica.

Il payload può quindi avere la seguente struttura:

{ "sub": "123", "name": "Alice", "exp": 30 }

Signature

La firma di un JSON Web Token è creata utilizzando la codifica Base64 dell’header e del payload e il metodo di firma/codifica specificato. La struttura è definita dalla JSON Web Signature (JWS), uno standard secondo RFC 7515. Affinché la firma funzioni, è necessario utilizzare una chiave segreta nota solo all’applicazione originale. Da un lato, questa firma verifica che il messaggio non sia stato modificato durante il percorso e dall’altro, se il token è firmato con una chiave privata, assicura che il mittente del JWT sia quello corretto.

A seconda della sensibilità dei dati, ci sono diverse procedure:

  1. Nessun backup: come precedentemente accennato, se il fattore di protezione dei dati è basso, può essere specificato il valore "none" nell’ header. In questo caso non viene generata alcuna firma. Quindi il JSON Web Token consiste solo di header e payload. Senza protezione, il payload è leggibile in chiaro dopo la decodifica di Base64 e non viene verificato se il messaggio provenga dal mittente corretto o se sia stato modificato in itinere.
  2. Firma (JWS): in genere è sufficiente controllare se i dati provengano dal mittente corretto e se siano stati modificati durante il percorso. Questo viene fatto utilizzando lo schema JSON Web Signature (JWS), che assicura che il messaggio non sia stato modificato durante il trasporto e che provenga dal mittente corretto. Con questa procedura, il carico utile può essere letto in chiaro anche dopo la decrittazione di Base64.
  3. Firma (JWS) e crittografia (JWE): è possibile utilizzare una JSON Web Encryption (JWE) in aggiunta al JWS. JWE cripta il contenuto del payload, che viene successivamente firmato con JWS. Per decifrare il contenuto, viene specificata una password comune o una chiave privata. Il mittente è quindi verificato, il messaggio è riservato e autentico e il payload non può essere letto in chiaro dopo la decrittazione di Base64.

Il processo di cifratura dà come risultato una sequenza di caratteri apparentemente casuale:

{ 7WK5T79u5mIzjIXXi2oI9Fglmgivv7RAJ7izyj9tUyQ }
N.B.

Per ciascuna delle procedure sopra menzionate, durante la comunicazione si dovrebbe in aggiunta utilizzare l’SSL, così da proteggere i dati.

Come funziona un JSON Web Token?

La funzione del JSON Web Token può essere spiegata molto bene con un login utente. Prima di utilizzare il JWT, è necessario definire una chiave segreta (secret). Una volta che un utente ha inserito con successo i propri dati di accesso, il JWT viene restituito con la chiave e memorizzato in locale. La trasmissione dovrebbe essere effettuata tramite HTTPS per proteggere meglio i dati.

Ogni volta che l’utente desidera accedere a risorse protette, ad esempio a un’API, o a un percorso protetto, lo User Agent invia il JWT come parametro (ad esempio ‘jwt’ per le GET request) o come intestazione di autorizzazione (per POST, PUT, OPTIONS, DELETE). Il partner di comunicazione è in grado di decifrare il JSON Web Token e, se il controllo va a buon fine, eseguire la richiesta.

N.B.

Dal momento che il JSON Web Token è un dato di accesso, non si deve tenere il token più a lungo del necessario e non si devono memorizzare dati sensibili nella memoria del browser.

Dove si applica il JSON Web Token?

JSON Web Token offre diversi vantaggi rispetto al tradizionale metodo di autenticazione e autorizzazione basato su cookie e viene utilizzato, tra l’altro, nei seguenti scenari:

  1. Applicazioni REST: nelle applicazioni REST, il JWT assicura che l’applicazione sia priva di stato, inviando le informazioni di autenticazione direttamente con la richiesta.
  2. Cross-Origin Ressource Sharing: JSON Web Token invia informazioni durante la condivisione di risorse cross-origin. Questo ha un enorme vantaggio rispetto ai cookie, che di solito non vengono inviati con questo metodo.
  3. Utilizzo di più framework: JSON Web Token è standardizzato e può essere utilizzato più volte Quando si utilizzano più framework, è più facile condividere i dati di autenticazione.

Come si implementa nella pratica un esempio di JWT?

Ricorrendo a un esempio di JWT, vogliamo mostrarvi come si presenta il token. A questo scopo, useremo l’header di esempio che abbiamo già menzionato all’inizio:

{
	"alg": "HS256",
	"typ": "JWT"
}

L’aspetto del payload del JSON Web Token potrebbe dunque essere simile a questo:

{
	"sub": "0123456789",
	"name": "Mario Rossi",
	"admin": true
}

Per ottenere l’effettiva struttura del JWT (tre parti separate da punti), l’header e il payload devono essere codificati con Base64. L’header sarà quindi come di seguito:

base64Header = base64Encode(header)
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Allo stesso modo sarà implementato nel payload:

base64Payload = base64Encode(payload)
// eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

Ora non resta che creare la firma. Nell’header abbiamo indicato che la firma è HMAC-SHA256:

signature = HS256(base64Header + '.' + base64Payload, 'secret')
// dyt0CoTl4WoVjAHI9Q_CwSKhl6d_9rhM3NrXuJttkao

L’ultimo passo è quello di unire queste tre parti insieme e separarle con un punto:

Token = base64Header + ‘.’ + base64Payload + ‘.’ + signature
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.dyt0CoTl4WoVjAHI9Q_CwSKhl6d_9rhM3NrXuJttkao

Ad oggi, la maggior parte dei linguaggi di programmazione fornisce librerie per la generazione di JSON Web Token, pertanto non è più necessaria l’implementazione manuale.

Per offrirti una migliore esperienza di navigazione online questo sito web usa dei cookie, propri e di terze parti. Continuando a navigare sul sito acconsenti all’utilizzo dei cookie. Scopri di più sull’uso dei cookie e sulla possibilità di modificarne le impostazioni o negare il consenso.