Verificarea semnăturii unui JSON Web Token (JWT)

verifică semnătura unui JWT (HS256, HS384, HS512, RS256, RS384, RS512) dintr-un secret sau cheie publică, și inspectează claim-urile sale
Pentru HS256 / HS384 / HS512: șirul secret. Pentru RS256 / RS384 / RS512: cheia publică în format PEM.

De ce să verifici semnătura unui JWT?

Un JSON Web Token (JWT) se descompune în trei părți separate de puncte: header.payload.signature. A decoda un JWT constă simplu în a citi primele două părți (care sunt Base64URL). Oricine poate face acest lucru, și oricine poate fabrica un JWT cu payload-ul ales. Ceea ce face un JWT demn de încredere este doar semnătura: fără verificare, a accepta un JWT echivalează cu a lăsa să intre la tine orice persoană care pretinde că este cineva, fără să ceri o piesă de identitate.

Acest instrument verifică semnătura a unui JWT plecând de la o cheie. Nu se mulțumește să decodeze: recalculează semnătura plecând de la header, payload și cheia ta, apoi o compară cu semnătura token-ului. Dacă cele două concordă, token-ul este autentic. Altfel, a fost forjat, modificat, sau semnat cu altă cheie.

Verificarea este piatra de temelie a oricărei arhitecturi care utilizează JWT-uri pentru autentificare sau autorizare: fără semnătură validă, payload-ul poate minți. Un atacator care ar modifica "role":"user" în "role":"admin" nu ar avea nicio dificultate să o facă dacă serverul ar verifica doar formatul token-ului și nu semnătura sa.

Algoritmi curenți

Specificația JWT (RFC 7518, JSON Web Algorithms) definește mai multe familii de algoritmi. Iată cele mai utilizate în producție:

  • HMAC (HS256, HS384, HS512): semnătură simetrică pe bază de HMAC-SHA. Aceeași cheie secretă servește la semnare și la verificare. Simplu de pus în loc, performant, dar orice parte capabilă să verifice token-ul este de asemenea capabilă să emită. Adaptat scenariilor unde emitentul și verificatorul sunt aceeași echipă sau același serviciu.
  • RSA (RS256, RS384, RS512): semnătură asimetrică. Cheia privată semnează, cheia publică verifică. Ideal când emitentul și verificatorii sunt entități distincte (OAuth2, OpenID Connect, federație de identitate). Este algoritmul privilegiat de majoritatea furnizorilor de identitate publici.
  • ECDSA (ES256, ES384): semnătură asimetrică pe curbe eliptice. Aceeași logică ca RSA (cheie privată pentru a semna, cheie publică pentru a verifica) dar cu chei și semnături mai compacte pentru un nivel de securitate echivalent. Din ce în ce mai răspândit în arhitecturile moderne.

Cum să furnizezi cheia

Formatul cheii așteptate depinde de algoritmul declarat în header-ul JWT-ului:

  • HS256, HS384, HS512: cheia este un șir secret (string). Este secretul partajat cu emitentul, adesea stocat într-o variabilă de mediu precum JWT_SECRET. Nicio punere în formă particulară, doar valoarea brută.
  • RS256, RS384, RS512: cheia este o cheie publică RSA în format PEM, care începe cu -----BEGIN PUBLIC KEY----- și se termină cu -----END PUBLIC KEY-----. Păstrează returnurile la linie ca atare, altfel OpenSSL refuză să o parseze.
  • ES256, ES384: cheia este o cheie publică ECDSA în format PEM, pe curba corespunzătoare (P-256 pentru ES256, P-384 pentru ES384).

Exemplu de cheie publică RSA așteptată

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxe...
...vQIDAQAB
-----END PUBLIC KEY-----

Cum funcționează verificarea?

Serverul nostru reproduce exact operația pe care a făcut-o emitentul:

  1. Separă JWT-ul în header, payload și semnătură.
  2. Concatenează base64url(header) + "." + base64url(payload).
  3. Pentru HMAC, calculează un HMAC-SHA-256/384/512 cu cheia ta secretă, apoi compară cu semnătura primită prin hash_equals (comparație în timp constant pentru a evita atacurile temporale).
  4. Pentru RSA, apelează openssl_verify cu cheia ta publică în format PEM.

Cazuri de utilizare

  • Debug de autentificare API: primești un 401, verifici dacă token-ul tău este într-adevăr semnat cu cheia așteptată.
  • Validare a unui token primit de la un furnizor: un partener (Auth0, Keycloak, Cognito, Okta) îți trimite JWT-uri semnate în RS256; vrei să confirmi că provin într-adevăr de la el cu cheia sa publică.
  • Audit de securitate: a verifica dacă un serviciu terț își semnează corect token-urile cu un algoritm robust, și nu în HS256 cu un secret slab.
  • Teste manuale: a verifica dacă un JWT generat de codul tău trece bine verificarea cu cheia publică furnizată.
  • Verificare rapidă a unui token primit: în timpul integrării unui SSO sau a unui API partener, a verifica în câteva secunde că lanțul semnătură/cheie funcționează înainte de a scrie cea mai mică linie de cod.

Cum să utilizezi instrumentul

  1. Lipește JWT-ul complet (cele trei părți separate de puncte).
  2. Indică cheia adaptată algoritmului header-ului:
    • Pentru HS256, HS384 sau HS512, cheia este șirul secret partajat cu emitentul. Este un șir liber, adesea stocat într-o variabilă de mediu precum JWT_SECRET.
    • Pentru RS256, RS384 sau RS512, cheia este cheia publică în format PEM, care începe cu -----BEGIN PUBLIC KEY----- și se termină cu -----END PUBLIC KEY-----.
  3. Lansează verificarea. Instrumentul afișează statutul (valid sau invalid) și payload-ul decodat.

Capcane curente de evitat

  • Algoritmul "none": specificația autorizează alg: none, care înseamnă "fără semnătură". O vulnerabilitate clasică constă în a fabrica un token cu acest header sperând ca serverul să-l accepte. Instrumentul nostru respinge sistematic token-urile cu alg: none.
  • Confuzie HMAC vs RSA (algorithm confusion): un atacator schimbă algoritmul RS256 în HS256 și semnează payload-ul cu cheia publică RSA utilizată ca secret HMAC. Dacă serverul nu controlează algoritmul, acceptă token-ul. Întotdeauna blochează algoritmul așteptat pe partea serverului.
  • Secrete HMAC în clar în cod: un secret commitat într-un depozit Git face toată încrederea token-urilor caducă. Stochează secretele în variabile de mediu sau într-un seif aplicativ.
  • Cheie publică vs cheie privată: pentru a verifica un JWT semnat în RSA sau ECDSA, se furnizează cheia publică, niciodată privata. Privata servește doar la semnare și nu trebuie niciodată să iasă de la emitent.
  • Expirare ignorată: o semnătură validă pe un token expirat nu trebuie niciodată să fie acceptată. Gândește-te să verifici exp și nbf.
  • Audiență necontrolată: un token destinat API-ului A nu ar trebui să fie acceptat de API-ul B. Verifică claim-ul aud.

Claim-uri temporale: exp și nbf

Dincolo de semnătură, un JWT valid trebuie să respecte și constrângerile sale temporale:

  • exp (expirare): token-ul nu mai este valid după această dată.
  • nbf (not before): token-ul nu este încă valid înainte de această dată.

Instrumentul nostru semnalează explicit când un token este expirat sau nu încă valid, chiar dacă semnătura sa este corectă. Este important: o semnătură validă pe un token expirat nu trebuie niciodată acceptată în producție.

Diferența cu JWT decoder-ul nostru

JWT decoder-ul nostru se mulțumește să decodeze părțile header și payload pentru a le face lizibile. Nu efectuează nicio verificare de semnătură și nu cere o cheie. Utilizează-l pentru a inspecta rapid conținutul unui token. Utilizează JWT verifier-ul (această pagină) imediat ce ai nevoie să dovedești că un token este autentic. Pentru a fabrica un JWT semnat în scop de test, utilizează JWT builder-ul nostru.

Întrebări frecvente

De ce RS256 în loc de HS256?

Cu HS256, emitentul și verificatorul partajează același secret: orice verificator poate deci să emită token-uri. Este gestionabil când se controlează ambele capete. Imediat ce se vorbește de un furnizor de identitate unic cu mai multe servicii consumatoare, se basculează în RS256: emitentul păstrează cheia privată, se distribuie cheia publică tuturor API-urilor care trebuie să verifice. Niciun API consumator nu poate atunci forja token-uri.

Cum să recuperez cheia publică a unui furnizor de identitate (IdP)?

Majoritatea IdP-urilor expun un endpoint JWKS standardizat (de exemplu https://exemplu.com/.well-known/jwks.json). Acest endpoint returnează un JSON conținând cheile publice active. Poți converti intrarea JWK care corespunde kid-ului header-ului JWT-ului tău în cheie PEM prin comanda openssl sau printr-o bibliotecă JWKS a stack-ului tău (de exemplu jose-jwt, jwks-rsa).

Ce să fac dacă verify eșuează?

Verifică mai întâi algoritmul: un token semnat în HS256 nu se verifică cu o cheie RSA, și invers. Verifică apoi cheia: un caracter alb în plus, un retur la linie lipsă într-o cheie PEM, sau un secret HMAC ușor diferit de cel utilizat de emitent sunt suficiente pentru a face verificarea să eșueze. Dacă IdP-ul a efectuat o rotație de cheie, kid-ul tău poate indica spre o cheie pe care nu o mai ai.

JWKS, ce este?

JWKS (JSON Web Key Set, RFC 7517) este un format JSON care descrie un set de chei publice. Fiecare cheie este identificată printr-un kid (key ID) iar JWT-ul de verificat referențiază acest kid în header-ul său. Mecanismul permite IdP-ului să-și rotească cheile fără a strica verificatorii: aceștia interoghează simplu endpoint-ul JWKS pentru a recupera cheia corespunzătoare kid-ului token-ului primit.

Cum să generez o pereche de chei RSA pentru a-mi semna JWT-urile?

Cu OpenSSL: openssl genrsa -out private.pem 2048 apoi openssl rsa -in private.pem -pubout -out public.pem. Cheia privată semnează pe partea emitentului, cheia publică verifică pe partea consumatorului. Pentru noi servicii, preferă 3072 sau 4096 biți.

Trebuie să criptez JWT-ul pe lângă a-l semna (JWE)?

Un JWT semnat (JWS) garantează integritatea și autenticitatea, dar payload-ul rămâne lizibil de oricine îl recuperează. Dacă token-ul conține date sensibile (identificatori interni, drepturi detaliate, date personale), ia în considerare formatul JWE (JSON Web Encryption) care criptează payload-ul pe lângă a-l semna.

Exemplu de cerere

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

Schema de intrare

Câmp Tip Obligatoriu Implicit
token text
key text

Puncte de acces

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