Decodarea unui JSON Web Token (JWT)

decodează token-ul dvs. JWT (JSON Web Token) și afișează informațiile pe care le conține într-un mod lizibil și structurat

Ce este un JWT (JSON Web Token)?

Un JSON Web Token, prescurtat în JWT (pronunțat "jot"), este un format compact definit de RFC 7519 permițând transportarea unei serii de revendicări (claims) între două părți. JWT-ul, sau token-ul JWT, este astăzi formatul dominant pentru a vehicula o identitate autentificată într-un API HTTP. Un JWT se prezintă ca un șir ASCII compus din trei segmente separate de puncte:

header.payload.signature

Fiecare segment este codat în Base64URL, o variantă a Base64 fără padding = și care înlocuiește + cu - și / cu _ pentru a putea circula într-un URL sau un header HTTP fără escape suplimentar.

Important: un JWT NU este criptat. Formatul JWT standard (JWS) este simplu semnat: semnătura garantează integritatea conținutului, dar nu aduce nicio confidențialitate. Oricine poate decoda payload-ul unui JWT cu un simplu Base64URL invers, așa cum face acest instrument jwt decode online.

Anatomia unui JWT

Un json web token este compus din trei părți bine distincte, fiecare jucând un rol precis în mecanismul de autentificare:

1. Header

Header-ul este un obiect JSON care descrie cum este semnat token-ul. Conține cel puțin:

  • alg (algorithm): algoritmul de semnătură utilizat. Valori tipice: HS256, RS256, ES256, EdDSA.
  • typ (type): tipul token-ului, aproape întotdeauna "JWT".
  • kid (key ID): facultativ, identifică ce cheie trebuie să fie utilizată pentru a verifica semnătura. Practic în prezența unui parc de chei în rotație (JWKS).

2. Payload

Payload-ul conține claim-urile, adică revendicările pe care emitentul le face despre utilizator sau sesiune. RFC 7519 definește șapte claim-uri standard (registered claims):

  • iss (issuer): cine a emis token-ul, de exemplu "https://accounts.google.com".
  • sub (subject): cui aparține token-ul, în practică identificatorul utilizatorului.
  • aud (audience): cui îi este destinat token-ul. Evită ca un token emis pentru API-ul A să fie acceptat de API-ul B.
  • exp (expiration time): timestamp Unix după care token-ul nu mai este valid.
  • nbf (not before): timestamp înainte de care token-ul nu este încă activ.
  • iat (issued at): timestamp de emitere a token-ului.
  • jti (JWT ID): identificator unic al token-ului, utilizat pentru revocare și prevenirea reluării.

La aceste claim-uri standard se adaugă în general claim-uri custom proprii aplicației (roles, scope, tenant_id, email, permissions...).

3. Semnătura

Semnătura este un condensat criptografic calculat pe base64url(header) + "." + base64url(payload) cu ajutorul unei chei. Ea este cea care dovedește că nimeni nu a modificat header-ul nici payload-ul de la emitere. Algoritmii cei mai curenți:

  • HS256 / HS384 / HS512: semnătură simetrică HMAC-SHA. O cheie secretă partajată între emitent și verificator. Simplu, dar nepotrivit imediat ce există mai mult de un consumator.
  • RS256 / RS384 / RS512: semnătură asimetrică RSA. Emitentul semnează cu cheia sa privată, orice consumator verifică cu cheia publică corespunzătoare. Standard de facto pentru OAuth2 și OpenID Connect.
  • ES256 / ES384 / ES512: semnătură asimetrică ECDSA. Aceleași proprietăți ca RS256 dar cu chei și semnături mult mai scurte.
  • EdDSA (Ed25519): semnătură asimetrică modernă, rapidă și compactă.

Încă o dată: semnătura protejează integritatea, nu confidențialitatea. Payload-ul rămâne lizibil de oricine deține token-ul.

De ce să decodezi un JWT?

Operația jwt token decode răspunde mai multor nevoi concrete pentru un dezvoltator sau inginer de securitate:

  • Debug de autentificare: API-ul tău returnează un 401 sau un 403, vrei să vezi ce se află realmente în payload (sub, scope, roles, exp) în loc să ghicești.
  • Verifică claim-urile: a confirma că un token conține într-adevăr revendicarea așteptată (de exemplu tenant_id sau permissions) înainte de a căuta în altă parte în lanțul de autorizare.
  • Citește expirarea: a converti timestamp-ul exp într-o dată umană pentru a confirma că un token este într-adevăr expirat, sau dimpotrivă că ar trebui să fie încă valid.
  • Audit de securitate: a te asigura că un serviciu terț nu scurge informații sensibile în payload (e-mail-uri, identificatori interni, date personale).
  • Formare și înțelegere: a vedea concret cum arată un jsonwebtoken ieșind dintr-un furnizor OAuth (Google, Auth0, Keycloak, AWS Cognito) pentru a înțelege mecanismul fără a te scufunda în doc.
  • Explorare a token-urilor publice: a inspecta un JWT găsit în log-uri, într-un cookie sau într-un schimb OAuth interceptabil.

Decoder vs Verifier: distincția critică

Cele două operații par vecine dar nu au nimic de a face în termeni de garanții de securitate:

  • A decoda un JWT constă în a decupa șirul pe . și a aplica un Base64URL invers primelor două segmente. Este o simplă citire, la îndemâna oricărui script de trei linii. Nicio verificare de semnătură nu este făcută.
  • A verifica un JWT constă în a recalcula semnătura plecând de la header, payload și o cheie, apoi a compara rezultatul cu semnătura prezentă în token. Este ceea ce garantează că token-ul nu a fost falsificat.

Concluzie practică: a decoda nu valorează cât a avea încredere. Atâta timp cât semnătura nu a fost verificată cu cheia bună, conținutul payload-ului poate fi total inventat. Pentru faza de încredere, utilizează JWT Verifier-ul nostru.

Cum să-l utilizezi

  1. Recuperează JWT-ul de inspectat, de exemplu dintr-un header Authorization: Bearer <jwt>, dintr-un cookie de sesiune, din localStorage-ul browserului, sau dintr-un log aplicativ.
  2. Lipește șirul complet în câmpul de intrare. Cele trei segmente trebuie să rămână separate de puncte.
  3. Instrumentul afișează imediat header-ul decodat în JSON formatat, cu algoritmul și tipul.
  4. Payload-ul este apoi decodat și afișat. Acolo vezi toate claim-urile standard și custom.
  5. Instrumentul indică de asemenea informația de semnătură (algoritm declarat, lungime), fără a o verifica.
  6. Pentru a confirma că token-ul nu a fost falsificat, basculează spre JWT Verifier-ul nostru cu cheia publică sau secretul așteptat.

Toată decodarea este efectuată în browserul tău în JavaScript: token-ul tău nu este niciodată trimis la serverele noastre.

JWT și securitate: capcanele de evitat

Nu stoca NICIODATĂ date sensibile în payload-ul unui JWT semnat.

Parole, numere de carduri bancare, date medicale, secrete API, identificatori interni critici: tot ceea ce se află în payload este lizibil de oricine deține token-ul, inclusiv utilizatorul însuși prin instrumentele de dezvoltare ale browserului său. Semnătura nu maschează nimic, doar dovedește că emitentul este într-adevăr cel care pretinde că este.

Câteva reguli de aur pentru a utiliza bine JWT-urile în producție:

  • Verifică întotdeauna semnătura pe partea serverului înainte de a acorda cel mai mic drept. JWT Verifier-ul nostru ilustrează exact această operație.
  • Preferă RS256 sau ES256 față de HS256 pentru API-uri publice. Semnătura asimetrică evită partajarea unui secret între emitent și fiecare consumator.
  • Respectă întotdeauna claim-ul exp. Un JWT fără expirare sau cu o expirare prea îndepărtată este o bombă cu ceas în caz de scurgere.
  • Validează iss și aud pe partea serverului, pentru a evita ca un token legitim emis pentru alt serviciu să fie acceptat din greșeală.
  • Refuză alg: "none" pe partea verificării. Este o vulnerabilitate clasică care permite unui atacator să forjeze orice payload.
  • Păstrează duratele de viață scurte (15 minute de exemplu) și cuplează cu un refresh token mai lung dar revocabil pe partea serverului.

Exemplu de jeton JWT decodat

Iată un JWT tipic:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjMiLCJuYW1lIjoiSm9obiIsImlhdCI6MTUxNjIzOTAyMn0.jrU9j8LZcRK2_BZjqXjU7lEpJbkqmXfTQIu9vT45j-I

Odată decodat, iată conținutul său:

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

// Payload
{
  "sub": "123",
  "name": "John",
  "iat": 1516239022
}

// Semnătură (binară, codată în Base64URL)
HMACSHA256(
  base64url(header) + "." + base64url(payload),
  secret
)

Unde să găsești un JWT de copiat?

În practică, un JWT de decriptat (în sensul de decodat) provine cel mai adesea dintr-unul din aceste locuri:

  • Cookie HTTP: deschide instrumentele de dezvoltare (F12), tab-ul Application sau Storage, apoi Cookies. Identifică un cookie numit access_token, jwt, session sau similar.
  • localStorage / sessionStorage: același panou, secțiunea Local Storage. Multe SPA-uri stochează token-ul lor acolo sub o cheie token sau auth.
  • Header Authorization: tab-ul Network, selectează o cerere API, citește header-ul Authorization: Bearer <jwt>. Copiază doar partea de după Bearer .
  • Log-uri server: un JWT apare uneori în log-urile unui gateway sau ale unui reverse proxy (de evitat în producție, dar util în debug).

Întrebări frecvente

JWT-ul este criptat sau în clar?

Un JWT semnat (format JWS) este doar codat în Base64URL, nu criptat. Orice persoană care interceptează un token poate citi payload-ul în câteva secunde. Dacă trebuie să transporți date cu adevărat confidențiale în token, trebuie să utilizezi formatul JWE (JSON Web Encryption), care adaugă un strat de criptare peste semnătură. În practică, JWE-ul rămâne rar: preferăm să nu punem date sensibile într-un token și să păstrăm informațiile critice în bază pe partea serverului.

Cum să revoc un JWT înainte de expirarea sa?

Este unul dintre punctele slabe ale JWT-ului: prin construcție, serverul nu are nevoie să stocheze starea token-ului, deci nu știe nici cum să-l marcheze ca revocat. Trei abordări există. Listă de revocare: a menține pe partea serverului lista jti-urilor invalidate, și a o consulta la fiecare cerere. Durate de viață scurte: a emite access token-uri valide 5 până la 15 minute, și a utiliza un refresh token revocabil pe partea serverului pentru a genera unele noi. Rotație a cheii de semnătură: a invalida o întreagă generație de token-uri schimbând cheia. A doua abordare este de departe cea mai răspândită.

Care este diferența între un JWT și o sesiune clasică?

O sesiune clasică stochează un identificator opac pe partea clientului (în general într-un cookie) și păstrează toate datele asociate (utilizator, drepturi, expirare) în memorie sau în bază pe partea serverului. Un JWT, dimpotrivă, transportă direct aceste date în token-ul semnat. Avantajul JWT: serverul nu are nevoie să stocheze sesiune, ceea ce simplifică scaling-ul orizontal și arhitectura microservicii. Inconveniente: revocarea este mai complexă, token-ul este mai voluminos la fiecare cerere, iar cea mai mică scurgere expune payload-ul.

Diferența între JWT, JWS și JWE?

JWT (RFC 7519) este un format de token generic. Poate fi implementat în două moduri concrete: JWS (RFC 7515, JSON Web Signature) care se mulțumește să semneze payload-ul, și JWE (RFC 7516, JSON Web Encryption) care îl criptează. În practică, când se vorbește de "JWT" fără precizare, se vorbește aproape întotdeauna de un JWS: un token semnat dar lizibil de toți. JWE-ul este utilizat în contexte unde confidențialitatea payload-ului este indispensabilă, de exemplu în anumite scenarii OpenID Connect avansate.

JWT-ul meu nu este acceptat de API, de ce?

Cauzele clasice sunt, în ordinea frecvenței: token expirat (verifică claim-ul exp), semnătură invalidă (cheia secretă sau cheia publică nu corespund celei utilizate de emitent), aud greșit (token-ul a fost emis pentru alt serviciu), iss greșit (emitentul declarat nu este cel așteptat), algoritm refuzat (API-ul cere de exemplu RS256 și primește un HS256), ceasuri desincronizate între emitent și verificator (joacă pe exp și nbf). Decodarea token-ului cu acest instrument permite deja eliminarea jumătății din ipoteze citind direct claim-urile.

Cum să generez un JWT?

Majoritatea limbajelor dispun de o bibliotecă dedicată: jsonwebtoken în Node.js, PyJWT în Python, lcobucci/jwt sau firebase/php-jwt în PHP, jjwt în Java, golang-jwt/jwt în Go. Toate iau ca intrare un obiect payload, o cheie și un algoritm, și returnează șirul header.payload.signature gata de trimis. Este puternic descurajată implementarea generării manuală: criptografia comportă prea multe capcane (comparații neconstante, gestionare incorectă a alg: none, etc.).

Decoder-ul acceptă un JWT expirat?

Da. Decoder-ul se mulțumește să afișeze conținutul token-ului fără a emite o judecată despre validitatea sa temporală. Nu evaluează nici exp, nici nbf, nici semnătura. Este util pentru a înțelege de ce un token a fost respins de un API: se poate compara valoarea exp-ului cu ora actuală pentru a confirma că este într-adevăr expirat.

JWT-ul meu este valid dacă decoder-ul îl afișează corect?

Nu. Afișarea dovedește doar că șirul este bine format (trei segmente separate de puncte, codare Base64URL corectă, JSON valid în header și în payload). Asta nu spune nimic despre autenticitatea token-ului. Un JWT integral falsificat poate fi afișat fără eroare într-un decoder, exact pentru aceasta trebuie trecut printr-un verifier.

Exemplu de cerere

curl -X POST https://cdrn.fr/api/v1/tools/jwt-decoder/execute \
  -H "Content-Type: application/json" \
  -d '{"token":"..."}'

Schema de intrare

Câmp Tip Obligatoriu Implicit
token text

Puncte de acces

  • GET https://cdrn.fr/api/v1/tools - listează toate instrumentele disponibile
  • GET https://cdrn.fr/api/v1/tools/jwt-decoder - obține schema acestui instrument
  • POST https://cdrn.fr/api/v1/tools/jwt-decoder/execute - execută acest instrument cu un payload JSON