JWT (JSON Web Token) — is een compact formaat voor gegevensoverdracht tussen partijen in de vorm van een JSON-object dat wordt beschermd door een digitale handtekening. De token kan worden ondertekend met HMAC (symmetrische sleutel) of RSA/ECDSA (asymmetrisch paar), wat de integriteit en authenticiteit van de gegevens garandeert. Volgens IETF RFC 7519, 2015 wordt JWT gebruikt in miljoenen applicaties voor authenticatie, veilige uitwisseling van claims en als ID Token-formaat in OpenID Connect.
Belangrijkste punten
JSON Web Token (JWT) — is een open standaard (RFC 7519) die een compacte en zelfstandige manier definieert om informatie tussen partijen over te dragen in de vorm van een JSON-object. Informatie in JWT wordt claims genoemd — beweringen over het subject (gebruiker) en extra attributen. Elke claim is een sleutel-waardepaar: gebruikers-ID, rol, vervaltijd, uitgever.
JWT wordt zelfstandig genoemd omdat alle informatie die nodig is voor verificatie zich in de token zelf bevindt. De server hoeft geen database of externe opslag te raadplegen om de geldigheid van de token te controleren — het volstaat om de handtekening te verifiëren. Deze eigenschap maakt JWT ideaal voor gedistribueerde systemen en microservice-architectuur, waar meerdere services verzoeken moeten authenticeren zonder gedeelde sessieopslag.
Volgens gegevens van Auth0, 2025 gebruikt meer dan 65% van de mobiele en webapplicaties JWT als primair tokenformaat voor API-authenticatie, waarmee het opaque tokens en sessie-ID's overtreft.
JWT bestaat uit drie delen gescheiden door punten: header.payload.signature. Elk deel is een Base64url-gecodeerde JSON. Laten we elk deel in detail bekijken.
Header bevat twee verplichte velden: alg (algorithm — handtekeningsalgoritme) en typ (type — tokentype, altijd „JWT”). Het algoritme kan symmetrisch (HS256 — HMAC met SHA-256) of asymmetrisch (RS256 — RSA met SHA-256, ES256 — ECDSA met P-256) zijn. Asymmetrische algoritmen hebben de voorkeur omdat de client de handtekening kan verifiëren zonder de geheime sleutel te bezitten.
Voorbeeld van gedecodeerde header:
{
"alg": "RS256",
"typ": "JWT",
"kid": "key-id-1"
}
Payload bevat claims — beweringen over het subject. Claims worden onderverdeeld in drie typen: geregistreerd (iss, sub, aud, exp, nbf, iat, jti), openbaar (door ontwikkelaar gedefinieerd in IANA Registry) en privé (tussen partijen overeengekomen). sub (subject) — unieke gebruikers-ID. exp (expiration) — timestamp van tokenverval. iss (issuer) — tokenuitgever.
{
"sub": "user-abc-123",
"iss": "https://auth.example.com",
"aud": "my-mobile-app",
"exp": 1812345678,
"iat": 1812342078,
"role": "premium_user"
}
Signature wordt gemaakt door het handtekeningsalgoritme toe te passen op de concatenatie van header en payload met behulp van een geheime of privésleutel. Formule: HMACSHA256(base64UrlEncode(header) + „.” + base64UrlEncode(payload), secret) voor HMAC, of RSASHA256(...) voor het asymmetrische algoritme. De ontvanger berekent de handtekening op dezelfde manier en vergelijkt deze met de ontvangene — als ze overeenkomen, zijn de gegevens niet gewijzigd.
Het werkingsproces van JWT bestaat uit twee fasen: het aanmaken (uitgeven) van de token door de authenticatieserver en het verifiëren van de token door de client of bronserver. De authenticatieserver ontvangt de inloggegevens van de gebruiker, maakt een payload met claims en ondertekent deze. De resulterende JWT wordt naar de client gestuurd als antwoord op het inlogverzoek of in de body van het OAuth 2.0 / OpenID Connect-antwoord.
In mobiele applicaties wordt JWT als volgt gebruikt: na succesvol inloggen ontvangt de gebruiker een access token in JWT-formaat. De applicatie slaat dit op in een beveiligde opslag (Keychain op iOS, EncryptedSharedPreferences op Android). Bij elk API-verzoek voegt de applicatie de header Authorization: Bearer <token> toe. De API-server verifieert de JWT-handtekening, extraheert claims en neemt op basis daarvan een toegangsbeslissing — zonder de database te raadplegen.
Volgens gegevens van Google Codelabs, 2025 vermindert het gebruik van JWT in Firebase Authentication het aantal verzoeken aan de authenticatieserver met 40–60% in vergelijking met sessietokens, omdat gegevens lokaal op elke microservice worden geverifieerd. Dit is vooral belangrijk in architecturen met hoge belasting, waar elke milliseconde vertraging de gebruikerservaring beïnvloedt. Bij 50.000 verzoeken per minuut kan de overstap naar JWT tot 10 serverinstanties besparen die introspection-verzoeken verwerken.
JWT en Session Token lossen dezelfde taak op — authenticatie van verzoeken — maar verschillen fundamenteel in architectuur. Session Token is een willekeurige identificatietekenreeks die verwijst naar sessiegegevens die op de server zijn opgeslagen (stateful). JWT — een zelfstandige token die alle gegevens in zich draagt (stateless).
| Parameter | JWT | Session Token |
|---|---|---|
| Gegevensopslag | In de token (zelfstandig) | Op de server (sessieopslag) |
| Schalen | Vereist geen gedeelde opslag | Vereist Redis/DB voor meerdere servers |
| Token intrekken | Complex (zwarte lijst nodig) | Eenvoudig (sessie uit DB verwijderen) |
| Grootte | Groot (500–2000 bytes) | Klein (16–64 bytes) |
| Handtekeningcontrole | Cryptografisch | Geen (tekenreeksvergelijking) |
JWT wint in gedistribueerde systemen: microservices kunnen de token lokaal verifiëren zonder gedeelde opslag. Bijvoorbeeld, in een architectuur met vijf microservices verifieert elke service JWT in 1–2 ms zonder netwerkaanroep, terwijl session token bij elk verzoek een gecentraliseerde Redis moet raadplegen, wat 10–30 ms vertraging toevoegt. JWT is echter moeilijk in te trekken — als de token eenmaal is uitgegeven, is deze geldig tot de vervaldatum. Session Token kan eenvoudig worden ingetrokken door het record uit DB of Redis te verwijderen.
Voor mobiele applicaties biedt een gecombineerde aanpak — JWT met een korte levensduur (15–30 minuten) en Refresh Token — een balans tussen prestaties en veiligheid. JWT wordt gebruikt voor API-toegang, en de refresh token (meestal opaque) voor het verkrijgen van nieuwe JWT's. Bij compromittering van JWT heeft de aanvaller 15–30 minuten toegang; bij compromittering van de refresh token wordt de sessie geblokkeerd via rotatie en hergebruikdetectie.
Veiligheid van JWT hangt af van correcte implementatie. De meest voorkomende kwetsbaarheid is de „alg none”-aanval: de aanvaller wijzigt de token-header naar „alg”: „none” en de server accepteert de vervalste token zonder het algoritme te controleren. Bescherming: controleer altijd of het algoritme in de header overeenkomt met het verwachte (RS256, ES256) en wijs tokens met alg: none af.
Kwetsbaarheden van JWT omvatten ook: zwakke geheime sleutel voor HMAC (binnen minuten te kraken), lekken van privésleutel (ondertekenen van willekeurige gegevens namens de server), opslag van gevoelige gegevens in payload (JWT versleutelt niet, alleen ondertekening), aanval via JWK header-injectie (invoegen van eigen openbare sleutel). Gebruik van vertrouwde bibliotheken — Nimbus JOSE + JWT, jjwt (io.jsonwebtoken), PyJWT — vermindert het risico op exploitatie van deze kwetsbaarheden.
Een extra beschermingsmaatregel is JWK Thumbprint (RFC 7638): het koppelen van de openbare sleutel aan de token via een vingerafdruk (thumbprint) in de header. Als de server de verwachte thumbprint voor elke client opslaat, wordt JWK header-injectie onmogelijk — de server wijst elke sleutel af die niet overeenkomt met de geregistreerde. OAuth Security Workshop 2025 beveelt JWK Thumbprint aan als verplichte bescherming voor alle JWT's die worden gebruikt in financiële en medische applicaties.
De bibliotheek jjwt (auth0/java-jwt) maakt het mogelijk om JWT's te maken en verifiëren in een Android-applicatie in enkele regels code. In het onderstaande voorbeeld genereert de server een token met sub en role, en verifieert de client de handtekening. Voor veilige opslag van de geheime sleutel op de server, gebruik omgevingsvariabelen of HSM (Hardware Security Module) — het opslaan van de sleutel in code of configuratiebestand is een grove veiligheidsfout.
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))
// Token naar client sturen
println("JWT: $token")
fun verifyToken(token: String): Boolean {
return try {
val decoded = JWT.require(Algorithm.HMAC256(secret))
.withIssuer("auth.example.com")
.build()
.verify(token)
// Handtekening is geldig, claims geëxtraheerd
println("Subject: ${decoded.subject}")
true
} catch (e: Exception) {
println("Token invalid: ${e.message}")
false
}
}
Veelgestelde vragen
Nee. JWT wordt ondertekend, niet versleuteld — iedereen kan de Base64-payload decoderen en de gegevens lezen. Gevoelige informatie (wachtwoorden, kaartnummers, persoonlijke gegevens) mag alleen versleuteld worden verzonden via JWE (JSON Web Encryption).
ES256 (ECDSA met P-256) wordt aanbevolen — het biedt een equivalent RSA 2048-bit veiligheidsniveau met een aanzienlijk kleinere handtekeninggrootte. Voor compatibiliteit met verouderde systemen is RS256 geschikt. HS256 (HMAC) vereist veilige uitwisseling van de geheime sleutel, wat moeilijker is in een gedistribueerde architectuur.
JWT kan niet direct worden ingetrokken — het is geldig tot exp. Oplossingen: gebruik een korte levensduur (15–30 minuten), houd een zwarte lijst bij van ingetrokken jti's (JWT ID) op de server, of koppel tokens aan de versie van de geheime sleutel. De refresh token wordt op de standaard manier ingetrokken — door verwijdering uit de opslag.
Bearer token — is een concept: elke token die de houder (bearer) kan gebruiken voor toegang. JWT — is een specifiek tokenformaat. Een Bearer token kan een JWT zijn of een opaque string. JWT voegt aan het Bearer-concept zelfstandigheid en cryptografische verificatie toe.
Een typische JWT met RS256-handtekening neemt 500–2000 bytes in beslag. Als de payload veel aangepaste claims bevat of een asymmetrische handtekening met een grote sleutel wordt gebruikt, kan de grootte 4–5 KB bereiken. Dit is aanzienlijk meer dan een session token (16–64 bytes), wat van invloed is op de grootte van HTTP-headers.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook