Un JWT, Json Web Token, è un particolare token crittografato, emesso lato server, che ha il compito di autorizzare le richieste in arrivo e di trasmettere informazioni in modo sicuro.

JWT è uno standard aperto (RFC 7519) che definisce un modo compatto e autonomo per la trasmissione sicura di informazioni tra le parti come un oggetto JSON. Queste informazioni possono essere verificate e considerate attendibili perché sono firmate digitalmente. I JWT possono essere firmati utilizzando un secret (con l’ algoritmo HMAC) o una coppia di chiavi pubblica/privata utilizzando RSA o ECDSA.

Struttura del JWT

Nella loro forma compatta, i token sono costituiti da tre parti separate da punti (.):

  • Header
  • Payload
  • Signature
header.payload.signature

Header

L’intestazione è in genere composta da due parti: il tipo di token, che è JWT, e l’algoritmo di firma utilizzato, come HMAC SHA256 o RSA.

Esempio

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

Quindi, questo JSON è codificato Base64Url per formare la prima parte del JWT.

Payload

Nel payload sono contenute tutte le informazioni che si vogliono scambiare. Solitamente si trovano i dati relativi all’utente: id, nome, ruoli…

{
  "id": "181867194676",
  "name": "John Doe",
  "role": "admin"
}

Signature

Attraverso l’intestazione codificata, il payload codificato, un secret e l’algoritmo specificato nell’intestazione, sarà possibile creare la firma del token.

Ad esempio, se si desidera utilizzare l’algoritmo HMAC SHA256, la firma verrà creata nel modo seguente:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

La firma viene utilizzata per verificare che il messaggio non sia stato modificato lungo il percorso e, nel caso di token firmati con una chiave privata, può anche verificare che il mittente del JWT sia chi dice di essere.

Meccanismo di autorizzazione

Come detto in precedenza, uno dei ruoli principali dei token JWT è l’autorizzazione. Il processo di autorizzazione avviene nel seguente modo:

Autenticazione

Nella prima fase del processo di autorizzazione, il client invia le credenziali di accesso al server (username, password…). Il server ne verifica la validità e – in caso affermativo – crea, firma e restituisce (solitamente nell’header authorization) il token JWT, nel quale sono presenti determinate informazioni dell’utente.

Autorizzazione

Dopo la fase di autenticazione, il client memorizza il token JWT emesso dal server così da rispedirlo ogni qualvolta avrà bisogno di risorse protette del server. Quest’ultimo lo recupererà dalla richiesta del client, lo verificherà e, se non vi saranno errori, procederà con l’elaborazione delle risorse.

Security

Un tema molto discusso è la sicurezza. I token JWT non sempre vengono utilizzati correttamente: spesso ne vengono tralasciati alcuni aspetti fondamentali che permetterebbero di tutelarsi da attacchi informatici.

Server to Server / Mobile App to Server

I token JWT vengono utilizzati anche per scambiare informazioni server to server o app to server con il medesimo funzionamento. Dal punto di vista della sicurezza, JWT funziona molto bene in quanto il richiedente non è soggetto in alcun modo a furti di token. Lo scambio del token in queste situazioni avviene solitamente per mezzo dell’header authorization.

Authorization: Bearer token_jwt
scambio dei JWT in struttura server to server o app to server

Client (Browser) to Server

L’architettura client (browser) to server, invece, è molto più vulnerabile in quanto vi è la necessità di memorizzare il token lato browser. La memoria del browser si identifica in due principali luoghi:

  • cookie;
  • local storage.

Nel primo caso, se il token viene salvato nei cookie è compromesso da CSRF (Cross Site Request Forgery), mentre nel secondo è soggetto a XSS (Cross Site Scripting). Vulnerabilità di questo tipo sono presenti in quanto sia i cookie, sia la memoria locale sono completamente accessibili e manipolabili dal javascript eseguito lato browser.

Ciò non significa che JWT non può essere utilizzato in questo tipo di architettura, ma che è necessario prendere alcuni accorgimenti.

L’idea principale è dividere il token JWT in 2 parti:

  • Header e Payload vanno memorizzati nella memoria locale
  • Signature va settata in un cookie di sessione lato server con l’opzione HttpOnly=true e SameSite=strict.

Un cookie di sessione con HttpOnly=true non permette al javascript lato browser di accedervi, mentre SameSite=strict forza la memorizzazione dell’informazione solamente su connessioni https.

schema illustrativo della struttura Client (Browser) to Server con accorgimenti di sicurezza

Con questi accorgimenti si riesce a mantenere un ottimo livello di sicurezza anche nelle applicazioni web.