---
term: 'JSON Web Token (JWT)'
seoTitle: 'JSON Web Token (JWT): struttura, claim, sicurezza, revoca'
headline: 'Che cos''è un JSON Web Token (JWT)?'
slug: json-web-token-jwt
category: auth-security
shortDefinition: 'Un JSON Web Token è un token compatto e sicuro per gli URL che trasporta claim JSON firmati e permette di verificare le richieste senza sessioni memorizzate.'
relatedTerms:
  - oauth-2-social-login
  - api-key-security
  - identity-access-management-iam
  - access-control-lists-acl
contrastsWith:
  - api-key-security
aboutTerms:
  - 'JWT Claims'
  - 'JWS (Signed JWT)'
  - 'Refresh Tokens'
faq:
  - question: 'Che cos''è un JWT in parole semplici?'
    answer: 'Una "carta d''identità" JSON firmata e codificata in Base64 che il server emette all''accesso. Il client la presenta a ogni richiesta e il server verifica la firma invece di cercare una sessione – il token stesso porta con sé chi è l''utente e fino a quando. Secondo la RFC che lo definisce, la pronuncia suggerita è quella della parola inglese "jot".'
  - question: 'Quali sono le tre parti di un JWT?'
    answer: 'Header (tipo di token e algoritmo di firma), payload (i claim – i dati JSON veri e propri) e firma, ciascuno codificato in Base64Url e uniti da punti in header.payload.signature. La firma è calcolata sulle prime due parti, quindi qualsiasi manomissione di quelle rompe la verifica.'
  - question: 'Un JWT è cifrato?'
    answer: 'No – codificato, non cifrato. Base64Url è un formato di trasporto che chiunque può invertire; basta incollare un JWT qualsiasi in un decodificatore e il payload si legge in chiaro. La firma impedisce la manomissione, non la lettura. Nel payload di un JWT non vanno mai messi segreti né dati personali sensibili; per le esigenze reali di riservatezza esiste la variante cifrata (JWE).'
  - question: 'Qual è la differenza tra un JWT e un token di sessione?'
    answer: 'Dove risiede lo stato. Un token di sessione è un ID opaco che punta a uno stato lato server – una lettura per richiesta, revocabile all''istante. Un JWT porta lo stato dentro di sé – nessuna lettura, verificabile da qualsiasi servizio che abbia la chiave, ma valido fino alla scadenza qualunque cosa accada. Scalabilità stateless contro controllo immediato.'
  - question: 'Dove conviene conservare un JWT nel browser?'
    answer: 'Non in localStorage – qualsiasi script iniettato può leggerlo, il che trasforma un XSS in un furto di token. Il consenso attuale: access token in memoria, refresh token in un cookie HttpOnly, Secure e SameSite, e vale la pena considerare il pattern backend-for-frontend, che tiene i token completamente fuori dal browser.'
  - question: 'Un JWT può essere revocato?'
    answer: 'Non per progetto – un token firmato è valido fino al suo claim exp, ed è il prezzo dell''assenza di stato. Tutti gli aggiramenti reintroducono stato: una denylist indicizzata sul claim jti, chiavi versionate oppure – la risposta standard – access token con vita molto breve abbinati a refresh token revocabili e a rotazione.'
  - question: 'Qual è la differenza tra HS256 e RS256?'
    answer: 'La simmetria. HS256 firma e verifica con un unico segreto condiviso – accettabile solo quando emittente e verificatore sono la stessa parte, e solo con un segreto lungo e casuale. RS256 (e il più recente Ed25519) firma con una chiave privata mentre chiunque verifica con quella pubblica – la scelta predefinita non appena più di un servizio controlla i token.'
  - question: 'Qual è la differenza tra JWT e OAuth?'
    answer: 'Categorie diverse: JWT è un formato di token; OAuth 2.0 è un framework di autorizzazione. Si compongono – i flussi OAuth emettono comunemente access token che sono anche JWT, e gli ID token di OpenID Connect lo sono sempre. Uno dice come è costruito un token; l''altro, come i token vengono distribuiti.'
codeLanguages: [javascript, dart, swift, kotlin]
externalAuthorities:
  - name: 'RFC 7519 — JSON Web Token (JWT)'
    url: 'https://datatracker.ietf.org/doc/html/rfc7519'
  - name: 'RFC 8725 — JWT Best Current Practices'
    url: 'https://datatracker.ietf.org/doc/html/rfc8725'
  - name: 'OWASP JSON Web Token Cheat Sheet'
    url: 'https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_Cheat_Sheet.html'
  - name: 'RFC 7515 — JSON Web Signature (JWS)'
    url: 'https://datatracker.ietf.org/doc/html/rfc7515'
  - name: 'JSON Web Token — Wikipedia'
    url: 'https://en.wikipedia.org/wiki/JSON_Web_Token'
cta:
  title: 'Un''autenticazione che ha già scelto'
  text: 'Back4app gestisce le sessioni con token revocabili, verifica lato server i JWT dei provider di identità per il login social e applica i permessi per singolo utente a ogni richiesta: l''igiene dei token diventa comportamento della piattaforma.'
  linkText: 'Inizia gratis'
  linkUrl: 'https://www.back4app.com/signup'
author: 'Back4app Engineering'
publishedDate: '2026-10-05'
translationKey: json-web-token-jwt
---

**Un JSON Web Token è un token compatto e sicuro per gli URL che trasporta claim JSON firmati e permette di verificare le richieste senza sessioni memorizzate.** È l'inquadramento della [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519) stessa – "un mezzo compatto e sicuro per gli URL di rappresentare claim da trasferire fra due parti" – e le due idee che contiene reggono tutto quello che segue: il token *contiene* i propri fatti, e una firma rende quei fatti *controllabili* da chiunque abbia la chiave giusta, senza alcun database nel giro.

## Punti chiave

| Domanda | Risposta |
| --- | --- |
| La forma | `header.payload.signature` – tre parti Base64Url unite da punti |
| Il trucco | Chiunque può *decodificarlo*; solo chi ha la chiave può *falsificarlo* |
| Non è crittografia | Il payload è leggibile – firmato ≠ segreto (è il compito di JWE) |
| Il baratto | Verifica stateless ↔ nessuna revoca integrata prima di `exp` |
| La disciplina | Fissare gli algoritmi · validare `iss`/`aud`/`exp` · vite brevi + rotazione dei refresh token |

## Un JWT, decodificato

```text
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 . eyJzdWIiOiJ1c3ItOGZrMiIsInJvbGUi… . dBjftJeZ4CVP…

header     { "alg": "HS256", "typ": "JWT" }
payload    { "sub": "usr-8fk2",  "role": "editor",
             "iss": "https://api.example.com",  "aud": "example-web",
             "iat": 1767024900,  "exp": 1767025800 }        ← durata: 15 minuti
signature  HMACSHA256( base64url(header) + "." + base64url(payload), secret )

Chiunque può DECODIFICARE le prime due parti – Base64Url è imballaggio, non crittografia.
Solo chi ha la chiave può FALSIFICARE la terza – ed è in questo che sta tutto il trucco.
```

Il contrasto che vale la pena vedere in codice – l'alternativa *con stato* su cui si misura ogni decisione sui JWT:

**JavaScript:**

```javascript
// JavaScript / Node.js — Back4app JS SDK
// The stateful contrast: Back4app issues revocable session tokens
const user = await Parse.User.logIn('ada', 'correct-horse-battery');
const token = user.getSessionToken(); // r:abc123… — opaque, server-side state
// Every request presents it; the server can revoke it instantly:
await Parse.User.logOut(); // token invalid NOW — no waiting for an exp claim
```

**Flutter:**

```dart
// Flutter / Dart — Back4app Flutter SDK
// The stateful contrast: Back4app issues revocable session tokens
final user = ParseUser('ada', 'correct-horse-battery', null);
await user.login();
final token = user.sessionToken; // r:abc123… — opaque, server-side state
// Every request presents it; the server can revoke it instantly:
await user.logout(); // token invalid NOW — no waiting for an exp claim
```

**Swift:**

```swift
// iOS / Swift — Back4app Swift SDK
// The stateful contrast: Back4app issues revocable session tokens
let user = try await User.login(username: "ada", password: "correct-horse-battery")
let token = user.sessionToken // r:abc123… — opaque, server-side state
// Every request presents it; the server can revoke it instantly:
try await User.logout() // token invalid NOW — no waiting for an exp claim
```

**Kotlin:**

```kotlin
// Android / Kotlin — Back4app Android SDK
// The stateful contrast: Back4app issues revocable session tokens
val user = ParseUser.logIn("ada", "correct-horse-battery")
val token = user.sessionToken // r:abc123… — opaque, server-side state
// Every request presents it; the server can revoke it instantly:
ParseUser.logOut() // token invalid NOW — no waiting for an exp claim
```

## Come funziona la verifica

```mermaid
flowchart LR
  accTitle: Flusso di emissione e verifica di un JWT
  accDescr: All'accesso il server firma un token che contiene i claim e lo restituisce al client. Il client lo conserva e lo invia come bearer token a ogni richiesta. Il server verifica la firma con la propria chiave e valida i claim, accettando o rifiutando senza alcuna lettura della sessione.
  L["Accesso<br/>(credenziali verificate una volta)"] --> S["Il server firma il JWT<br/>claim + chiave"]
  S --> C["Il client conserva il token"]
  C -->|"Authorization: Bearer eyJ…"| V["Qualsiasi server con la chiave:<br/>verifica la firma · valida i claim"]
  V -->|"valido"| OK["La richiesta prosegue<br/>nessuna lettura di sessione"]
  V -->|"manomesso / scaduto / aud errata"| NO["401"]
```

La precisione che le spiegazioni saltano: "JWT" nomina il formato dei claim; ciò che tutti fanno realmente circolare è un **JWS** ([RFC 7515](https://datatracker.ietf.org/doc/html/rfc7515)) – la serializzazione *firmata* – mentre **JWE** è il fratello cifrato, per i payload che devono restare illeggibili. E la verifica sono due lavori, non uno: controllare la firma e poi **validare i claim** – `exp` e `nbf` contro l'orologio, `iss` contro la propria lista di emittenti consentiti, `aud` contro l'identificatore di *questo* servizio. Un token firmato alla perfezione ma scaduto, proveniente dall'emittente sbagliato o coniato per un'altra audience è un attacco firmato alla perfezione.

## I claim: il vocabolario del payload

| Claim | Nome | Compito di chi verifica |
| --- | --- | --- |
| `iss` | Emittente (issuer) | È un emittente di cui fidarsi? |
| `sub` | Soggetto (subject) | Di chi si parla – l'ID utente stabile |
| `aud` | Audience | È stato coniato per *me*? Rifiutare i token altrui |
| `exp` | Scadenza (expiration) | Rifiutare dopo questo timestamp Unix |
| `iat` / `nbf` | Emesso il / non prima di | Verificare la coerenza della finestra di validità |
| `jti` | ID del token | Identificatore univoco – l'aggancio di cui una denylist ha bisogno |
| *personalizzati* | Ruoli, tenant, piano… | Semantica dell'app – minima, mai segreta |

Conviene tenere i payload leggeri per due motivi: i token viaggiano a ogni richiesta negli header (i cookie si fermano intorno ai 4 KB, e ogni claim è banda ripetuta) e tutto ciò che contengono è leggibile da chiunque detenga il token.

## JWT vs. token di sessione

| | JWT (stateless) | Token di sessione (con stato) |
| --- | --- | --- |
| Il token è | Lo stato stesso, firmato | Un puntatore opaco allo stato del server |
| Costo per richiesta | Controllo della firma, nessuna lettura | Una lettura nell'archivio delle sessioni |
| Revoca | **Nessuna fino a `exp`** – per progetto | Istantanea – si elimina la sessione |
| Auth fra servizi | Verifica qualsiasi servizio che abbia la chiave | I servizi devono condividere l'archivio delle sessioni |
| Disconnettersi significa | Il client lo scarta; il token resta valido | Il token muore davvero |
| Casa ideale | API, microservizi, verifica da parte di terzi | App con un solo backend, sessioni sensibili |

La verità fuori moda con cui diverse guide di buone pratiche ormai aprono: per un'app renderizzata lato server con un solo backend, le sessioni del framework sono più semplici *e* più controllabili – i JWT si guadagnano il posto quando i token devono essere verificati fra servizi o da parti che non possono interpellare l'emittente a ogni richiesta.

## Il problema della revoca, onestamente

L'assenza di stato *è* l'impossibilità di revocare – la stessa proprietà, descritta due volte. Un token firmato è valido fino a `exp` qualunque cosa sia successa nel frattempo: disconnessione, cambio di password, blocco dell'account. Ogni rimedio reintroduce stato, quindi resta solo da scegliere il gusto: una **denylist** indicizzata su `jti` + `iss` (la costruzione [raccomandata da OWASP](https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_Cheat_Sheet.html)) consultata a ogni richiesta – poco stato, ma pur sempre stato; il **versionamento delle chiavi**, che revoca *tutti* in un colpo solo; oppure l'architettura standard – **access token a vita breve (5–15 minuti) più refresh token revocabili** con rotazione: ogni rinnovo emette un nuovo refresh token e ritira il vecchio, così che uno rubato muoia al primo riutilizzo, e il riuso di un token ritirato segnala il furto e uccide l'intera famiglia di token. La latenza di revoca diventa allora pari alla vita dell'access token – ed è la vera ragione per cui quelle vite sono brevi.

## Scegliere un algoritmo – e gli attacchi a quella scelta

| | HS256 (HMAC) | RS256 (RSA) | Ed25519 / ES256 |
| --- | --- | --- | --- |
| Chiavi | Un solo segreto condiviso | La privata firma, la pubblica verifica | La privata firma, la pubblica verifica |
| A chi verifica serve | Il *segreto* (con cui si può anche falsificare!) | Solo la chiave pubblica | Solo la chiave pubblica |
| Adatto a | Emittente = verificatore, una sola parte | Multi-servizio, terze parti | Idem, firme più piccole e veloci |
| Spigolo vivo | I segreti corti si rompono per forza bruta offline a partire da un solo token catturato – usare ≥ 256 bit casuali | Token più grandi, più lento | Supporto delle librerie più recente |

La sezione sugli attacchi per cui esiste la [RFC 8725](https://datatracker.ietf.org/doc/html/rfc8725), in tre frasi. `alg: "none"` è un valore di header legale – le librerie che lo onorano accettano token non firmati. L'attacco per confusione: un verificatore che lascia scegliere l'algoritmo all'*header del token* può ricevere un token "HS256" firmato con la chiave RSA *pubblica* del server usata come segreto HMAC – un valore pubblico impiegato come valore privato. Entrambi muoiono allo stesso modo: **chi verifica fissa nella configurazione gli algoritmi e le chiavi che accetta e non si fida mai dell'header per la scelta.**

## Dove conservare i JWT nel browser

| Posizione | L'XSS lo ruba? | Il CSRF lo invia? | Sopravvive al ricaricamento? | Verdetto |
| --- | --- | --- | --- | --- |
| localStorage | **Sì** | No | Sì | Da evitare – leggibile dagli script |
| Cookie semplice | Sì (leggibile dagli script) | **Sì** | Sì | Il peggio di entrambi |
| Cookie HttpOnly + Secure + SameSite | No | Mitigato da SameSite | Sì | Bene – per il refresh token |
| In memoria | Solo finché dura l'iniezione | No | No | Bene – per l'access token |
| I token restano nel backend-for-frontend | Il browser non li ha mai | Valgono le regole dei cookie | Sì | Il più solido per le SPA |

Conta il modello di minaccia, non il folklore: localStorage baratta l'immunità al CSRF con il furto via XSS, i cookie barattano l'inverso – ed è per questo che il consenso divide la coppia: access token in memoria, refresh token in un cookie irrobustito.

## Casi d'uso tipici

- **Autenticazione di API** – il bearer token dietro gli header `Authorization` delle API [REST](/glossary/it/api-rest/) e GraphQL.
- **Identità nei microservizi** – un solo token emesso dalla gateway e verificato in modo indipendente da ogni servizio, senza archivio di sessioni condiviso.
- **ID token di OpenID Connect** – l'asserzione di identità firmata di ogni [login social](/glossary/it/oauth-2-login-social/) – sempre un JWT.
- **Passaggi di consegne fra sistemi** – link firmati, payload di webhook, autorizzazioni al download: claim verificati da una parte che non può richiamare l'emittente.
- **Indizi di autorizzazione stateless** – ruoli e ID di tenant trasportati nei claim, con il controllo che fa fede sempre lato server.

## JWT o sessioni? Matrice decisionale

| Situazione | Scegliere |
| --- | --- |
| Un solo backend, app renderizzata lato server | Le sessioni – più semplici, revocabili all'istante |
| API pubblica consumata da molti servizi | I JWT, con chiavi asimmetriche |
| Microservizi dietro una gateway | I JWT – verifica locale, nessun archivio condiviso |
| Il blocco immediato è un requisito inderogabile | Le sessioni, oppure JWT + denylist ed `exp` breve |
| Terze parti devono verificare le asserzioni emesse | I JWT – è il terreno di casa del formato |
| App mobile davanti a un BaaS | Il meccanismo di sessione della piattaforma – ha già scelto |

## Limiti e trade-off

- **L'irrevocabilità è strutturale.** Ogni mitigazione – denylist, vite brevi, rotazione – è un rientro parziale dello stato che era stato tolto; va messa nel conto prima di scegliere il modello stateless.
- **I claim invecchiano.** I ruoli sono un'istantanea scattata all'emissione; un amministratore retrocesso resta amministratore fino alla scadenza. Le vite brevi limitano la finestra di obsolescenza.
- **Il payload è pubblico.** Va trattato come leggibile dall'utente e da qualsiasi ladro di token: identificatori sì, segreti e dati personali no.
- **I valori predefiniti delle librerie hanno fatto vittime.** Fissare gli algoritmi, validare i claim e controllare `typ` sono responsabilità della propria configurazione, non garanzie della libreria.
- **La dimensione si accumula.** Ogni claim viaggia a ogni richiesta; payload generosi tassano la banda mobile e possono sforare i limiti dei cookie.

## I token su Back4app

Back4app è una piattaforma open-source di Backend as a Service (BaaS) che combina database gestito, API REST e GraphQL generate automaticamente, autenticazione, archiviazione di file e funzioni serverless con Cloud Code. La scelta della piattaforma stessa illustra la matrice decisionale: le sessioni dei client usano **token di sessione revocabili, lato server** – le schede di codice qui sopra – così che disconnessione, cambi di password e chiusura della sessione dalla dashboard abbiano effetto immediato, senza finestre di scadenza da attendere. I JWT compaiono dove è giusto che siano: gli ID token OIDC dei provider di identità vengono verificati lato server dagli adattatori di autenticazione durante il [login social](/glossary/it/oauth-2-login-social/), e le funzioni Cloud Code possono coniare o verificare JWT per i passaggi di consegne con terze parti usando librerie standard – con il segreto di firma nella configurazione lato server, mai spedito ai client. Con stato dove conta il controllo, stateless ai bordi dove la verifica deve viaggiare: l'architettura che questo articolo difende, già assemblata.
