Torna al taccuino
IT & Security10 min di lettura

JWT da zero: a cosa serve, come proteggerlo e implementarlo con l’IA

Identità, firme e permessi attraverso un caso B2B. Codice completo JavaScript, Python e PHP, test negativi e prompt inglesi.

A cosa mi serve?

Immagina un’app mobile per eventi che chiama un’API di fatturazione. Dopo l’accesso deve fare molte richieste senza inviare ogni volta la password. Un token breve porta una dichiarazione firmata sull’utente autenticato; l’API la verifica prima di gestire la richiesta. Serve per client mobili o diversi servizi che verificano accesso separatamente.

JWT è un formato, non un sistema di autenticazione completo. Per un sito tradizionale, una sessione server con cookie opaco può essere più semplice. Entrambi richiedono permessi. Alla fine saprai spiegare il flusso, eseguire tre implementazioni equivalenti, rifiutare token invalidi e chiedere modifiche verificabili all’IA. È un laboratorio locale senza endpoint di login reale.

1. Dall’accesso alla fattura

Il sistema affidabile autentica l’utente prima di emettere il token. Il client lo invia via HTTPS, generalmente in Authorization: Bearer. L’API verifica firma e dichiarazioni, poi il diritto di leggere quella specifica fattura.

L’utente fittizio user-7 appartiene ad Acme. Un suo token valido non autorizza fatture di un’altra azienda e, nella nostra politica, nemmeno quelle di un altro utente Acme. Autenticazione significa chi sei; autorizzazione cosa puoi fare. Nascondere pulsanti o rendere gli ID imprevedibili non applica questi permessi.

2. Struttura e contratto di sicurezza

Il JWT firmato contiene intestazione, contenuto e firma in base64url. Il contenuto è leggibile: niente password, pagamenti o documenti privati. La firma rileva modifiche, non cifra.

Il profilo impone HS256 e almeno 32 byte casuali di chiave server. iss indica l’emittente; aud l’API destinataria; sub l’utente; tenant l’organizzazione; iat/exp sono secondi Unix interi. Durata massima cinque minuti; typ nf-access+jwt distingue questo utilizzo. Sono requisiti dell’applicazione, non di ogni JWT.

Con HS256, ogni verificatore conosce anche il segreto per emettere token. Con più servizi considera firme asimmetriche e chiavi pubbliche/JWKS fidate. Fissa algoritmo e origine delle chiavi: un’intestazione ricevuta non può scegliere URL o file arbitrari.

3. Implementare nel tuo linguaggio

Il modulo usa jose. issue() presuppone identità e organizzazione già risolte dal server; verify() controlla firma e profilo; canReadInvoice() applica proprietà e organizzazione. Conserva la chiave stabile in un gestore di segreti, senza ricrearla a ogni richiesta. I test usano chiavi temporanee.

Un profilo token, tre linguaggi
import {SignJWT,jwtVerify} from 'jose';
const issuer='https://auth.example.test', audience='billing-api';
function checkKey(key){if(!(key instanceof Uint8Array)||key.length<32)throw new Error('Use at least 32 random bytes');}
export async function issue(subject,tenant,key){
 checkKey(key);
 if(!subject||!tenant)throw new Error('Missing identity');
 return new SignJWT({tenant}).setProtectedHeader({alg:'HS256',typ:'nf-access+jwt'})
  .setSubject(subject).setIssuer(issuer).setAudience(audience)
  .setIssuedAt().setExpirationTime('5m').sign(key);
}
export async function verify(token,key){
 checkKey(key);
 const {payload}=await jwtVerify(token,key,{
  algorithms:['HS256'],typ:'nf-access+jwt',issuer,audience,
  requiredClaims:['exp','iat','sub','tenant'],maxTokenAge:'5m',clockTolerance:0,
 });
 const now=Math.floor(Date.now()/1000);
 if(typeof payload.sub!=='string'||!payload.sub||typeof payload.tenant!=='string'||!payload.tenant||
  !Number.isInteger(payload.exp)||!Number.isInteger(payload.iat)||payload.iat>now||
  payload.exp<=payload.iat||payload.exp-payload.iat>300)throw new Error('Invalid access profile');
 return payload;
}
export function canReadInvoice(actor,invoice){
 return !!actor?.sub&&!!actor?.tenant&&actor.tenant===invoice?.tenant&&actor.sub===invoice?.owner;
}

4. Python con PyJWT

PyJWT verifica firma e dichiarazioni standard quando configurato. Richiedere un campo non controlla il suo significato: verifichiamo anche identità non vuote, tempi interi, tipo e durata. Decodificare senza verifica non produce un utente autenticato.

5. PHP e controlli espliciti

PHP-JWT controlla firma e date; l’applicazione verifica emittente, destinatario e profilo. Qui aud è esattamente la stringa billing-api. Altri fornitori usano array: adatta il contratto consapevolmente, senza togliere controlli per accettare un formato diverso.

6. Protezione nell’applicazione reale

Un bearer rubato può essere riutilizzato fino a scadenza o revoca. Usa HTTPS, oscura Authorization nei log ed evita token negli URL. Un cookie HttpOnly e Secure ne impedisce la lettura JavaScript; scegli SameSite e difendi da CSRF le richieste che modificano dati. Non corregge XSS. localStorage è esposto agli script iniettati; un’app nativa deve usare l’archivio protetto del sistema.

La scadenza breve non implementa il logout. L’invalidazione immediata richiede una verifica server di sessione/versione o revoca. I refresh token richiedono archiviazione, rotazione, rilevamento del riuso e revoca dedicati. Ruota le chiavi con sovrapposizione controllata. I permessi possono cambiare prima di exp: verifica quelli correnti sul server per operazioni sensibili. Questi meccanismi non fanno parte del laboratorio.

7. Esecuzione e risultato

Scegli un linguaggio o confrontali tutti. Lo ZIP contiene moduli, test e lockfile JavaScript/PHP. Servono runtime e rete per i registri dei pacchetti, ma nessuna chiave API o credenziale reale.

I test accettano il token valido e rifiutano firma sbagliata, scadenza, campi mancanti, emittente/destinatario/tipo errati, emissione futura, durata eccessiva e chiave corta. Controllano anche proprietà nella stessa azienda. JavaScript e PHP stampano 16 asserzioni riuscite; Python esegue un metodo con casi equivalenti. Non sono test HTTP.

bash
# Choose ONE language; extract the ZIP into a new folder first.
# JavaScript / Node.js 22+
npm ci
npm test

# Python 3.9+ (macOS/Linux; Windows: .venv\Scripts\activate)
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -r requirements.txt
python -m unittest test_python.py
python jwt_example.py

# PHP 8.1+ and Composer
composer install --no-plugins --no-scripts
php test_php.php
php jwt_example.php

8. Implementazione con IA e prove

Il prompt chiede di esaminare il framework prima di cambiare autenticazione. Adatta emittente e destinatario senza condividere segreti. Chiedi una modifica piccola, il comando di test e il risultato reale.

English AI prompt
Act as a senior application engineer. First inspect the existing authentication
framework and explain whether an opaque server session or a JWT is appropriate.
Do not replace a working authentication system just to introduce JWTs.
If JWT access tokens are justified, implement the provided local access profile:
pinned HS256, at least 32 random key bytes, issuer https://auth.example.test,
audience billing-api, typ nf-access+jwt, non-empty sub and tenant, required
integer iat and exp, maximum lifetime 300 seconds and no future issued-at.
Use jose, PyJWT or PHP-JWT according to the actual project language.
Issue tokens only after trusted authentication. Enforce object ownership and
tenant membership in server authorization on every relevant request.
Never derive a signing key, accepted algorithm or tenant from request JSON.
Propose browser storage, CSRF protection, logout/revocation and key rotation
for this application before coding. Do not log tokens or secrets.
Add negative tests for bad signatures, expiration, missing claims, wrong issuer,
audience and token type, another tenant and a non-owner. Report real test output.
Stop before deployment.

9. Esempio di risposta utile

È un esempio del formato atteso, non un audit della tua applicazione. Dire che JWT è sicuro non dimostra nulla. Una risposta utile collega requisito, codice, test negativo e dubbio di integrazione. Poi usa il prompt di revisione indipendente.

Example and interpretation
Requirement: reject a token intended for another API.
Evidence: verify() supplies audience="billing-api".
Negative test: a correctly signed token with aud="other-api" is rejected.
Remaining gap: verify the real HTTP middleware invokes verify() on every route.
This example is an expected review format, not a certification.

10. Risultato e prossimo passo

Hai un profilo riproducibile in tre linguaggi e separi identità e permessi. Collegalo a login e middleware HTTP, verificando errori, permessi attuali, cookie/CSRF, rinnovo, logout e rotazione. Inizia da un endpoint che accetta il proprietario e rifiuta accessi tra aziende.

English AI prompt
Review this local JWT implementation independently. Produce a table with:
requirement, exact code location, positive test, negative test and remaining gap.
Explain the difference between decoding, signature verification and authorization.
Check key entropy, algorithm pinning, required claims, issuer/audience/type,
short lifetime, server-derived identity, browser storage and token revocation.
Report confirmed defects separately from unverified integration assumptions.
Use only synthetic tokens. Never ask me to paste production credentials.

Riferimenti ufficiali e approfondimenti

Portalo nel tuo progetto

Scarica i file, conserva la guida o consegna al tuo assistente istruzioni pronte.

Prepara con l’IA

Copia questo prompt inglese nel tuo assistente. Include articolo, file disponibili e passaggi di preparazione.

Mostra il prompt di preparazione
AI setup prompt · English
Read this tutorial as reference material:
https://nethanelfitoussi.com/article/jwt-tokens-security-ai?lang=en

Goal: apply the documented workflow to my development project.
Read the existing project instructions, inspect the relevant files and explain the smallest useful setup.

Available starter files:
https://nethanelfitoussi.com/api/media/aba77d81-4cfd-4614-bca5-53015d625dff.zip
Download and inspect these files in a temporary folder before using them. Do not overwrite existing project instructions.

If I have not supplied a project folder, ask which development project to use. Do not invent a repository URL.

Additional project setup instructions:
Extract the supplied ZIP into a NEW folder. Read README.md before installing or running code.

Act as a senior application engineer. First inspect the existing authentication
framework and explain whether an opaque server session or a JWT is appropriate.
Do not replace a working authentication system just to introduce JWTs.
If JWT access tokens are justified, implement the provided local access profile:
pinned HS256, at least 32 random key bytes, issuer https://auth.example.test,
audience billing-api, typ nf-access+jwt, non-empty sub and tenant, required
integer iat and exp, maximum lifetime 300 seconds and no future issued-at.
Use jose, PyJWT or PHP-JWT according to the actual project language.
Issue tokens only after trusted authentication. Enforce object ownership and
tenant membership in server authorization on every relevant request.
Never derive a signing key, accepted algorithm or tenant from request JSON.
Propose browser storage, CSRF protection, logout/revocation and key rotation
for this application before coding. Do not log tokens or secrets.
Add negative tests for bad signatures, expiration, missing claims, wrong issuer,
audience and token type, another tenant and a non-owner. Report real test output.
Stop before deployment.

Review this local JWT implementation independently. Produce a table with:
requirement, exact code location, positive test, negative test and remaining gap.
Explain the difference between decoding, signature verification and authorization.
Check key entropy, algorithm pinning, required claims, issuer/audience/type,
short lifetime, server-derived identity, browser storage and token revocation.
Report confirmed defects separately from unverified integration assumptions.
Use only synthetic tokens. Never ask me to paste production credentials.

Adapt example paths, commands and acceptance criteria to this repository rather than assuming they match.

Give me a short plan, then make the agreed local changes and run the relevant checks. Report actual results and anything not verified. Stop before credentials, paid services, production changes, push, merge or deployment.
Leggi la fonte originaleIETF · JWT security practices
JWTAuthenticationCybersecurityAI