Leer wat een JWT (JSON Web Token) is, hoe de drie onderdelen werken, waar het wordt gebruikt en belangrijke beveiligingstips om veelvoorkomende tokenfouten te vermijden.

Een JWT (JSON Web Token) is een compacte, URL-veilige string die een set informatie vertegenwoordigt (meestal over een gebruiker of sessie) op een manier die tussen systemen kan worden doorgegeven. Je ziet het vaak als een lange waarde die begint met iets als eyJ..., meegestuurd in een HTTP-header zoals Authorization: Bearer \u003ctoken\u003e.
Traditionele logins vertrouwen vaak op server-sessies: nadat je hebt ingelogd, slaat de server sessiegegevens op en geeft de browser een session-ID-cookie. Elke aanvraag bevat die cookie en de server zoekt de sessie op.
Met tokengebaseerde authenticatie kan de server vermijden om voor elke gebruiker state bij te houden. In plaats daarvan houdt de client een token (zoals een JWT) en voegt dat toe aan API-aanroepen. Dit is populair voor API's omdat het:
Belangrijke nuance: “stateless” betekent niet “nooit server-side controles”. Veel echte systemen valideren tokens nog steeds tegen gebruikersstatus, roterende sleutels of intrekkingsmechanismen.
JWT's dragen vaak bewijs van authenticatie (je bent ingelogd) en basis hints voor autorisatie (rollen, permissies, scopes) — maar je server moet toch autorisatieregels afdwingen.
Je ziet JWT's vaak als access tokens in:
Een JWT is een compacte string met drie delen, elk base64url-gecodeerd en gescheiden door punten:
header.payload.signature
Voorbeeld (geredigeerd):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNzAwMDAwMDAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c…
De header beschrijft hoe het token is gemaakt—het belangrijkste is het ondertekeningsalgoritme (bijv. HS256, RS256/ES256) en het tokentype.
Veelvoorkomende velden:
typ: vaak "JWT" (meestal genegeerd in de praktijk)alg: het gebruikte ondertekeningsalgoritmekid: een key identifier om de verifier te helpen de juiste sleutel te kiezen tijdens rotatieBeveiligingsopmerking: vertrouw de header niet klakkeloos. Handhaaf een allowlist van algoritmen die je daadwerkelijk gebruikt, en accepteer niet alg: "none".
De payload bevat “claims” (velden) over de gebruiker en de context van het token: voor wie het is, wie het heeft uitgegeven en wanneer het verloopt.
Belangrijk: JWT's zijn standaard niet versleuteld. Base64url-codering maakt het token URL-veilig; het verbergt de data niet. Iedereen die het token krijgt, kan de header en payload decoden.
Daarom moet je vermijden geheimen (wachtwoorden, API-sleutels) of gevoelige persoonlijke gegevens in een JWT te zetten.
De signature wordt gemaakt door de header + payload te ondertekenen met een sleutel:
De signature biedt integriteit: de server kan verifiëren dat het token niet is aangepast en door een vertrouwde ondertekenaar is aangemaakt. Het biedt geen vertrouwelijkheid.
Omdat een JWT header en payload bevat bij elke aanvraag waarin het wordt meegestuurd, betekenen grotere tokens meer bandbreedte en overhead. Houd claims compact en geef de voorkeur aan identifiers boven omvangrijke data.
Claims vallen meestal in twee categorieën: registered (gestandaardiseerde namen) en custom (veldjes van je app).
iss (issuer): wie het token heeft gemaaktsub (subject): over wie het token gaat (vaak een gebruikers-ID)aud (audience): voor wie het token bedoeld is (bijv. een specifieke API)exp (expiration time): wanneer het token niet meer geaccepteerd mag wordeniat (issued at): wanneer het token is aangemaaktnbf (not before): het token mag niet vóór deze tijd worden geaccepteerdNeem alleen op wat de ontvangende service echt nodig heeft om een autorisatiebeslissing te nemen.
Goede voorbeelden:
user_id)Vermijd “convenience claims” die veel profieldata dupliceren. Ze maken het token groot, raken snel verouderd en vergroten de impact als het token lekt.
Omdat de payload leesbaar is, zet er niet in:
Als je gevoelige informatie nodig hebt, sla die server-side op en zet alleen een referentie (zoals een ID) in het token—of gebruik een versleuteld tokenformaat (JWE) waar dat passend is.
Ondertekening is geen encryptie.
Wanneer een JWT wordt uitgegeven, ondertekent de server de gecodeerde header + payload. Wanneer het token later wordt gepresenteerd, recomputeert de server de signature en vergelijkt die. Als iemand één teken verandert (bijv. "role":"user" naar "role":"admin"), faalt de verificatie en wordt het token afgewezen.
JWT is een tokenformaat. OAuth 2.0 en OpenID Connect (OIDC) zijn protocollen die beschrijven hoe apps tokens opvragen, uitgeven en gebruiken.
OAuth 2.0 gaat vooral over autorisatie: een app toegang geven tot een API namens een gebruiker zonder het wachtwoord te delen.
Access tokens zijn typisch kortlevend (minuten). Korte levensduur beperkt schade bij lekkage.
OIDC voegt authenticatie (wie is de gebruiker) toe bovenop OAuth 2.0 en introduceert een ID token, dat meestal een JWT is.
Een belangrijke regel: gebruik geen ID token om een API aan te roepen.
Als je meer context wilt over praktische flows, zie de blogpost over JWT-authenticatieflows.
Een typische flow ziet er zo uit:
De gebruiker logt in (email/wachtwoord, SSO, enz.). Als dat lukt, maakt de server een JWT (vaak een access token) met essentiële claims zoals subject en vervaltatum.
De server ondertekent het token en retourneert het aan de client (webapp, mobiele app of een andere service).
Voor beschermde endpoints voegt de client de JWT toe in de Authorization header:
Authorization: Bearer \u003cJWT\u003e
Voordat de aanvraag wordt bediend, controleert de API doorgaans:
exp (niet verlopen)iss (verwachte issuer)aud (bedoeld voor deze API)Als alle controles slagen, beschouwt de API de gebruiker als geauthenticeerd en past autorisatieregels toe (bijv. record-level permissies).
Omdat systeemklokken kunnen afwijken, laten veel systemen kleine clock skew toe bij het valideren van tijdgebaseerde claims zoals exp (en soms nbf). Houd de skew klein om te voorkomen dat je de geldigheid van tokens onbedoeld verlengt.
De opslagkeuze verandert wat aanvallers kunnen stelen en hoe makkelijk ze een token kunnen hergebruiken.
In-geheugen opslag (vaak aanbevolen voor SPA's) houdt het access token in JS-state. Het wordt gewist bij refresh en vermindert het risico op later stelen, maar een XSS-bug kan het nog steeds uitlezen tijdens het draaien van de pagina. Combineer dit met kortlevende access tokens en een refresh-flow.
localStorage/sessionStorage zijn makkelijk maar riskant: elke XSS kan tokens exfiltreren uit webopslag. Als je ze gebruikt, beschouw XSS-preventie als ononderhandelbaar (CSP, escaping, dependency hygiene) en houd tokens kortlevend.
Secure cookies (vaak de veiligste standaard voor web) slaan tokens op in een HttpOnly cookie zodat JavaScript ze niet kan lezen—dit vermindert de impact van XSS-diefstal. Het nadeel is CSRF-risico, omdat browsers cookies automatisch meesturen.
Als je cookies gebruikt, zet dan:
HttpOnlySecure (alleen HTTPS)SameSite=Lax of SameSite=Strict (sommige cross-site flows hebben SameSite=None; Secure nodig)Overweeg ook CSRF-tokens voor state-changing requests.
Op iOS/Android bewaar je tokens in de platformsecure storage (Keychain / Keystore-backed storage). Vermijd platte bestanden of preferences. Als je dreigingsmodel geroot/jailbroken devices omvat, ga ervan uit dat extractie mogelijk is en vertrouw op kortlevende tokens en server-side controles.
Beperk wat een token kan doen: gebruik minimale scopes/claims, houd toegangstokens kortlevend en vermijd het insluiten van gevoelige data.
JWT's zijn handig, maar veel incidenten ontstaan door voorspelbare fouten. Behandel een JWT als contant geld: wie het heeft, kan het vaak uitgeven.
Als een token dagen of weken geldig is, geeft een lek een aanvaller dat hele venster.
Geef de voorkeur aan kortlevende access tokens (minuten) en vernieuw ze via een veiliger mechanisme. Als je “remember me” nodig hebt, doe dat met refresh tokens en server-side controles.
Geldige handtekeningen zijn niet genoeg. Controleer iss en aud, en valideer tijdclaims zoals exp en nbf.
Decoderen is geen verificatie. Verifieer altijd de handtekening op de server en handhaaf permissies server-side.
Vermijd het plaatsen van JWT's in queryparameters. Ze kunnen in browsergeschiedenis, serverlogs, analytics en referrer-headers terechtkomen.
Gebruik in plaats daarvan Authorization: Bearer ....
Ga ervan uit dat sleutels en tokens kunnen lekken. Roteer signing keys, gebruik kid om soepele rotatie te ondersteunen en heb een intrekkingsstrategie (korte vervaltijden + mogelijkheid om accounts/sessies uit te schakelen). Voor opslagadvies, zie de blogpost over waar JWT's veilig te bewaren.
JWT's zijn nuttig, maar ze zijn niet automatisch de beste keuze. De echte vraag is of je profiteert van een self-contained token dat geverifieerd kan worden zonder bij elke aanvraag een database-opvraging.
Voor traditionele server-gerenderde webapps waar eenvoudige invalidatie belangrijk is, zijn server-side sessies met HttpOnly cookies vaak de simpelere, veiligere standaard.
Kies JWT als je stateless verificatie tussen services nodig hebt en je tokens kortlevend kunt houden.
Vermijd JWT als je onmiddellijke intrekking nodig hebt, je van plan bent gevoelige data in het token te bewaren, of je sessiecookies zonder frictie kunt gebruiken.
Verifieer met de juiste sleutel en verwacht algoritme. Weiger ongeldige handtekeningen—geen uitzonderingen.
exp (expiration)Zorg dat het token niet is verlopen.
nbf (not before)Als aanwezig, zorg dat het token niet te vroeg wordt gebruikt.
aud (audience)Bevestig dat het token voor jouw API/service bedoeld is.
iss (issuer)Bevestig dat het token van de verwachte issuer komt.
Valideer token-formaat, handhaaf maximale grootte en weiger onverwachte claim-types om edge-case bugs te verminderen.
HS256 (symmetrische sleutel): één gedeeld geheim ondertekent en verifieert.
RS256 / ES256 (asymmetrische sleutels): private key ondertekent; public key verifieert.
Vuistregel: als meer dan één onafhankelijk systeem tokens moet verifiëren (of je vertrouwt niet elke verifier volledig), geef dan de voorkeur aan RS256/ES256.
iss, aud en een gebruikers-ID alleen als beleid dat toestaat).Is JWT versleuteld?
Niet standaard. De meeste JWT's zijn ondertekend, niet versleuteld, wat betekent dat de inhoud door iedereen gelezen kan worden die het token heeft. Gebruik JWE of laat gevoelige data buiten JWT's.
Kan ik een JWT intrekken?
Niet eenvoudig als je alleen op self-contained access tokens vertrouwt. Gebruikelijke benaderingen zijn kortelevende access tokens, deny-lists voor hoge-risico gebeurtenissen, of refresh tokens met rotatie.
Hoe lang moet exp zijn?
Zo kort als je UX en architectuur toelaten. Veel API's gebruiken minuten voor access tokens, gecombineerd met refresh tokens voor langere sessies.
Als je JWT-auth implementeert in een nieuwe API of SPA, is veel werk repetitief: middleware aansluiten, iss/aud/exp valideren, cookieflags instellen en tokenafhandeling uit logs houden.
Met Koder.ai kun je snel een webapp (React), backendservices (Go + PostgreSQL) of een Flutter mobiele app genereren via een chatgestuurde workflow—dan itereren in een planningsmodus, snapshots en rollback gebruiken terwijl je beveiliging verfijnt, en de broncode exporteren wanneer je klaar bent. Het is een praktische manier om JWT-authflows te versnellen en toch controle te houden over verificatielogica, sleutelrotatie en deployment/hosting-instellingen (inclusief custom domains).
Een JWT (JSON Web Token) is een compacte, URL-veilige string die claims (gegevensvelden) bevat en door een server geverifieerd kan worden. Het wordt vaak bij API-aanvragen meegestuurd via:
Authorization: Bearer \u003ctoken\u003eHet kernidee: de server kan de integriteit van het token valideren (via de handtekening) zonder voor elke aanvraag een per-gebruiker sessieregister te hoeven raadplegen.
Sessie-authenticatie slaat doorgaans state op de server (een sessierecord gekoppeld aan een cookie/session ID). Bij JWT-gebaseerde auth presenteert de client bij elke aanvraag een ondertekend token dat de API valideert.
JWT's zijn populair voor API's en multi-service-architecturen omdat verificatie lokaal kan gebeuren, wat de behoefte aan gedeelde sessieopslag vermindert.
“Stateless” omvat nog steeds vaak server-side controles zoals deny-lists, controle van gebruikersstatus of key-rotatie.
Een JWT bestaat uit drie Base64URL-gecodeerde onderdelen, gescheiden door punten:
header.payload.signatureDe header beschrijft hoe het token is ondertekend, de payload bevat claims (zoals sub, exp, aud) en de signature laat de server detecteren of er is geknoeid.
Nee. Standaard JWT's zijn meestal ondertekend, niet versleuteld.
Als je vertrouwelijkheid nodig hebt, overweeg dan JWE (versleutelde tokens) of bewaar gevoelige data server-side en zet alleen een verwijzing in het JWT.
De handtekening laat de server verifiëren dat het token niet is aangepast en is uitgegeven door iemand met de juiste sleutel.
Het garandeert niet:
exp automatisch ingetrokken isBehandel een token als een credential: als het lekt, kan het doorgaans worden hergebruikt totdat het verloopt.
alg vertelt welke algoritme is gebruikt (bijv. HS256 vs RS256). kid is een key identifier die helpt om tijdens key-rotatie de juiste verificatiesleutel te kiezen.
Veiligheidsregels:
Begin met gestandaardiseerde registered claims en houd custom claims minimaal.
Veelvoorkomende registered claims:
JWT is een tokenformaat; OAuth 2.0 en OpenID Connect zijn protocollen.
Typische mapping:
Voor browser-apps zijn de gebruikelijke opties:
localStorage/sessionStorage: handig, maar elke XSS kan tokens exfiltreren.Minimaal moet je valideren:
exp (niet verlopen)iss (verwachte issuer)aud (bedoeld voor jouw API)nbf (als aanwezig)Voeg ook praktische guardrails toe:
alg-waarden.alg: "none".kid-waarde het sleutelzoekgedrag niet onveilig maken.iss (issuer)sub (subject / gebruikers-ID)aud (audience / bedoelde API)exp (expiration)iat (issued at)nbf (not before)Vermijd het plaatsen van geheimen of gevoelige persoonsgegevens in de payload, omdat die leesbaar zijn als het token wordt gelekt.
Belangrijk: gebruik geen ID token om een API aan te roepen alleen omdat het “eruitziet” als een JWT-access token.
SameSite + CSRF-tokens voor state-changing requests).Wat je ook kiest: maak toegangstokens kortlevend en minimaliseer token-privileges.