JWT (JSON Web Token) — este un format compact de transmitere a datelor între părți sub forma unui obiect JSON protejat prin semnătură digitală. Tokenul poate fi semnat cu HMAC (cheie simetrică) sau RSA/ECDSA (pereche asimetrică), ceea ce garantează integritatea și autenticitatea datelor. Conform IETF RFC 7519, 2015, JWT este utilizat în milioane de aplicații pentru autentificare, schimb securizat de claims și ca format ID Token în OpenID Connect.
Principalele
JSON Web Token (JWT) — este un standard deschis (RFC 7519) care definește un mod compact și autosuficient de transmitere a informațiilor între părți sub forma unui obiect JSON. Informațiile din JWT se numesc claims — declarații despre subiect (utilizator) și atribute suplimentare. Fiecare claim este o pereche cheie-valoare: identificatorul utilizatorului, rolul, data expirării, emitentul.
JWT se numește autosuficient deoarece toate informațiile necesare pentru verificare se află în interiorul tokenului însuși. Serverul nu trebuie să acceseze baza de date sau stocarea externă pentru a se asigura de validitatea tokenului — este suficient să verifice semnătura. Această proprietate face JWT ideal pentru sisteme distribuite și arhitectura microserviciilor, unde mai multe servicii trebuie să autentifice solicitări fără o stocare comună a sesiunilor.
Conform datelor Auth0, 2025, peste 65% dintre aplicațiile mobile și web utilizează JWT ca format principal de token pentru autentificarea API, depășind tokenurile opaque și identificatorii de sesiune.
JWT constă din trei părți separate prin puncte: header.payload.signature. Fiecare parte este un JSON codat Base64url. Să examinăm fiecare parte în detaliu.
Header conține două câmpuri obligatorii: alg (algorithm — algoritmul de semnare) și typ (type — tipul tokenului, întotdeauna „JWT”). Algoritmul poate fi simetric (HS256 — HMAC cu SHA-256) sau asimetric (RS256 — RSA cu SHA-256, ES256 — ECDSA cu P-256). Algoritmii asimetrici sunt preferați deoarece permit clientului să verifice semnătura fără a deține cheia secretă.
Exemplu de header decodat:
{
"alg": "RS256",
"typ": "JWT",
"kid": "key-id-1"
}
Payload conține claims — declarații despre subiect. Claims se împart în trei tipuri: înregistrate (iss, sub, aud, exp, nbf, iat, jti), publice (definite de dezvoltator în IANA Registry) și private (convenite între părți). sub (subject) — identificatorul unic al utilizatorului. exp (expiration) — timestampul expirării tokenului. iss (issuer) — emitentul tokenului.
{
"sub": "user-abc-123",
"iss": "https://auth.example.com",
"aud": "my-mobile-app",
"exp": 1812345678,
"iat": 1812342078,
"role": "premium_user"
}
Signature se creează prin aplicarea algoritmului de semnare la concatenarea header și payload folosind o cheie secretă sau privată. Formula: HMACSHA256(base64UrlEncode(header) + „.” + base64UrlEncode(payload), secret) pentru HMAC, sau RSASHA256(...) pentru algoritmul asimetric. Destinatarul calculează semnătura în același mod și o compară cu cea primită — dacă coincid, datele nu au fost modificate.
Procesul de funcționare cu JWT constă din două faze: crearea (emiterea) tokenului de către serverul de autentificare și verificarea tokenului de către client sau serverul de resurse. Serverul de autentificare primește datele de autentificare ale utilizatorului, creează payload cu claims și îl semnează. JWT-ul rezultat este trimis clientului ca răspuns la cererea de autentificare sau în corpul răspunsului OAuth 2.0 / OpenID Connect.
În aplicațiile mobile JWT este utilizat astfel: după autentificarea reușită, utilizatorul primește un access token în format JWT. Aplicația îl stochează într-un depozit securizat (Keychain pe iOS, EncryptedSharedPreferences pe Android). La fiecare solicitare către API, aplicația adaugă antetul Authorization: Bearer <token>. Serverul API verifică semnătura JWT, extrage claims și pe baza acestora ia decizia de acces — fără a accesa baza de date.
Conform datelor Google Codelabs, 2025, utilizarea JWT în Firebase Authentication reduce numărul de solicitări către serverul de autentificare cu 40–60% comparativ cu tokenurile de sesiune, deoarece datele sunt verificate local pe fiecare microserviciu. Acest lucru este deosebit de important în arhitecturile cu sarcină mare, unde fiecare milisecundă de întârziere afectează experiența utilizatorului. La 50 000 de solicitări pe minut, trecerea la JWT poate economisi până la 10 instanțe de server care procesează cererile de introspection.
JWT și Session Token rezolvă aceeași sarcină — autentificarea solicitărilor — dar diferă fundamental prin arhitectură. Session Token este un șir identificator aleatoriu care face referire la datele sesiunii stocate pe server (stateful). JWT — un token autosuficient care conține toate datele în sine (stateless).
| Parametru | JWT | Session Token |
|---|---|---|
| Stocarea datelor | În interiorul tokenului (autosuficient) | Pe server (stocare sesiune) |
| Scalare | Nu necesită stocare partajată | Necesită Redis/DB pentru mai multe servere |
| Revocare token | Complexă (necesită listă neagră) | Simplă (ștergerea sesiunii din DB) |
| Dimensiune | Mare (500–2000 de octeți) | Mică (16–64 de octeți) |
| Verificare semnătură | Criptografică | Nu (comparare șiruri) |
JWT câștigă în sistemele distribuite: microserviciile pot verifica tokenul local fără stocare partajată. De exemplu, într-o arhitectură cu cinci microservicii, fiecare serviciu verifică JWT în 1–2 ms fără apel de rețea, în timp ce session token necesită accesarea unui Redis centralizat la fiecare solicitare, adăugând 10–30 ms de întârziere. Cu toate acestea, JWT este dificil de revocat — dacă tokenul a fost deja emis, este valabil până la expirare. Session Token se revocă ușor, ștergând înregistrarea din DB sau Redis.
Pentru aplicațiile mobile, abordarea combinată — JWT cu durată scurtă de viață (15–30 de minute) și Refresh Token — oferă un echilibru între performanță și securitate. JWT este utilizat pentru accesul la API, iar refresh token (de obicei opaque) pentru obținerea de noi JWT-uri. La compromiterea JWT-ului, atacatorul are acces pentru 15–30 de minute; la compromiterea refresh token-ului, sesiunea este blocată prin rotație și detectarea reutilizării.
Securitatea JWT depinde de implementarea corectă. Cea mai frecventă vulnerabilitate este atacul „alg none”: atacatorul modifică header-ul tokenului la „alg”: „none”, iar serverul, fără a verifica algoritmul, acceptă tokenul fals. Protecție: verificați întotdeauna că algoritmul din header corespunde celui așteptat (RS256, ES256) și respingeți tokenurile cu alg: none.
Vulnerabilitățile JWT includ, de asemenea: cheia secretă slabă pentru HMAC (spargere în câteva minute), scurgerea cheii private (semnarea oricăror date în numele serverului), stocarea datelor sensibile în payload (JWT nu criptează, doar semnează), atacul prin injectare JWK header (introducerea propriilor chei publice). Utilizarea bibliotecilor verificate — Nimbus JOSE + JWT, jjwt (io.jsonwebtoken), PyJWT — reduce riscul exploatării acestor vulnerabilități.
O măsură suplimentară de protecție — JWK Thumbprint (RFC 7638): legarea cheii publice de token prin amprentă (thumbprint) în header. Dacă serverul stochează amprenta așteptată pentru fiecare client, atacul de injectare JWK header devine imposibil — serverul respinge orice cheie care nu se potrivește cu cea înregistrată. OAuth Security Workshop 2025 recomandă JWK Thumbprint ca protecție obligatorie pentru toate JWT-urile utilizate în aplicații financiare și medicale.
Biblioteca jjwt (auth0/java-jwt) permite crearea și verificarea JWT-urilor într-o aplicație Android în câteva rânduri. În exemplul de mai jos, serverul generează un token cu sub și role, iar clientul verifică semnătura. Pentru stocarea sigură a cheii secrete pe server, utilizați variabile de mediu sau HSM (Hardware Security Module) — stocarea cheii în cod sau fișier de configurare este o eroare gravă de securitate.
val secret = "my-256-bit-secret-key-here"
val token = JWT.create()
.withSubject("user-abc-123")
.withIssuer("auth.example.com")
.withClaim("role", "premium_user")
.withExpiresAt(Date(System.currentTimeMillis() + 3600000))
.sign(Algorithm.HMAC256(secret))
// Trimiterea tokenului către client
println("JWT: $token")
fun verifyToken(token: String): Boolean {
return try {
val decoded = JWT.require(Algorithm.HMAC256(secret))
.withIssuer("auth.example.com")
.build()
.verify(token)
// Semnătura este corectă, claims extrase
println("Subject: ${decoded.subject}")
true
} catch (e: Exception) {
println("Token invalid: ${e.message}")
false
}
}
Întrebări frecvente
Nu. JWT este semnat, nu criptat — oricine poate decoda payload-ul Base64 și poate citi datele. Informațiile sensibile (parole, numere de card, date personale) trebuie transmise doar în formă criptată prin JWE (JSON Web Encryption).
Este recomandat ES256 (ECDSA cu P-256) — oferă un nivel de securitate echivalent RSA 2048-bit cu o dimensiune semnificativ mai mică a semnăturii. Pentru compatibilitate cu sistemele moștenite, este potrivit RS256. HS256 (HMAC) necesită schimbul securizat al cheii secrete, ceea ce este mai dificil într-o arhitectură distribuită.
JWT nu poate fi revocat direct — este valabil până la exp. Soluții: utilizați o durată scurtă de viață (15–30 de minute), mențineți o listă neagră de jti (JWT ID) revocate pe server sau asociați tokenurile cu versiunea cheii secrete. Refresh token-ul este revocat în mod standard — prin ștergerea din stocare.
Bearer token — este un concept: orice token pe care posesorul (bearer) îl poate utiliza pentru acces. JWT — este un format specific de token. Bearer token poate fi un JWT sau un string opaque. JWT adaugă conceptului Bearer autosuficiența și verificarea criptografică.
Un JWT tipic cu semnătură RS256 ocupă 500–2000 de octeți. Dacă payload-ul conține multe claims personalizate sau se utilizează o semnătură asimetrică cu o cheie mare, dimensiunea poate ajunge la 4–5 KB. Aceasta este semnificativ mai mare decât session token (16–64 octeți), ceea ce afectează dimensiunea antetelor HTTP.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și