De handtekening van een JSON Web Token (JWT) verifiëren

verifieert de handtekening van een JWT (HS256, HS384, HS512, RS256, RS384, RS512) met een geheim of een publieke sleutel, en inspecteert de claims
Voor HS256 / HS384 / HS512: de gedeelde geheime string. Voor RS256 / RS384 / RS512: de publieke sleutel in PEM-formaat.

Waarom de handtekening van een JWT verifiëren?

Een JSON Web Token (JWT) bestaat uit drie delen gescheiden door punten: header.payload.signature. Een JWT decoderen bestaat eenvoudig uit het lezen van de eerste twee delen (die Base64URL zijn). Iedereen kan het doen, en iedereen kan een JWT met de payload van zijn keuze fabriceren. Wat een JWT betrouwbaar maakt, is alleen de handtekening: zonder verificatie is een JWT accepteren hetzelfde als bij u thuis elke persoon binnenlaten die beweert iemand te zijn, zonder identiteitsbewijs te vragen.

Deze tool verifieert de handtekening van een JWT vanuit een sleutel. Hij beperkt zich niet tot het decoderen: hij berekent de handtekening opnieuw vanuit de header, de payload en uw sleutel, en vergelijkt deze vervolgens met de handtekening van het token. Als beide overeenkomen, is het token authentiek. Anders is het gesmeed, gewijzigd of ondertekend met een andere sleutel.

De verificatie is de hoeksteen van elke architectuur die JWT's gebruikt voor authenticatie of autorisatie: zonder geldige handtekening kan de payload liegen. Een aanvaller die "role":"user" wijzigt naar "role":"admin" zou geen moeite hebben om het te doen als de server alleen het formaat van het token verifieert en niet de handtekening.

Gangbare algoritmen

De JWT-specificatie (RFC 7518, JSON Web Algorithms) definieert verschillende families van algoritmen. Dit zijn de meest gebruikte in productie:

  • HMAC (HS256, HS384, HS512): symmetrische handtekening gebaseerd op HMAC-SHA. De zelfde geheime sleutel dient om te ondertekenen en te verifiëren. Eenvoudig te implementeren, performant, maar elke partij die het token kan verifiëren is ook in staat om er een uit te geven. Geschikt voor scenario's waar de uitgever en de verificateur hetzelfde team of dezelfde service zijn.
  • RSA (RS256, RS384, RS512): asymmetrische handtekening. De privésleutel ondertekent, de publieke sleutel verifieert. Ideaal wanneer de uitgever en de verificateurs verschillende entiteiten zijn (OAuth2, OpenID Connect, identiteitsfederatie). Het is het voorkeursalgoritme van de meeste publieke identiteitsproviders.
  • ECDSA (ES256, ES384): asymmetrische handtekening op elliptische krommen. Zelfde logica als RSA (privésleutel om te ondertekenen, publieke sleutel om te verifiëren) maar met compactere sleutels en handtekeningen voor een equivalent beveiligingsniveau. Steeds vaker gebruikt in moderne architecturen.

Hoe de sleutel aanleveren

Het formaat van de verwachte sleutel hangt af van het algoritme dat in de header van de JWT is gedeclareerd:

  • HS256, HS384, HS512: de sleutel is een geheime tekenreeks (string). Het is het geheim gedeeld met de uitgever, vaak opgeslagen in een omgevingsvariabele zoals JWT_SECRET. Geen bijzondere opmaak, gewoon de ruwe waarde.
  • RS256, RS384, RS512: de sleutel is een publieke RSA-sleutel in PEM-formaat, die begint met -----BEGIN PUBLIC KEY----- en eindigt met -----END PUBLIC KEY-----. Bewaar de regeleinden als zodanig, anders weigert OpenSSL deze te parsen.
  • ES256, ES384: de sleutel is een publieke ECDSA-sleutel in PEM-formaat, op de overeenkomstige kromme (P-256 voor ES256, P-384 voor ES384).

Voorbeeld van een verwachte publieke RSA-sleutel

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

Hoe werkt de verificatie?

Onze server reproduceert precies de bewerking die de uitgever heeft uitgevoerd:

  1. Hij scheidt de JWT in header, payload en handtekening.
  2. Hij voegt base64url(header) + "." + base64url(payload) samen.
  3. Voor HMAC berekent hij een HMAC-SHA-256/384/512 met uw geheime sleutel, en vergelijkt vervolgens met de ontvangen handtekening via hash_equals (vergelijking met constante tijd om temporele aanvallen te vermijden).
  4. Voor RSA roept hij openssl_verify aan met uw publieke sleutel in PEM-formaat.

Gebruiksgevallen

  • API-authenticatie-debug: u ontvangt een 401, controleer of uw token correct is ondertekend met de verwachte sleutel.
  • Validatie van een token ontvangen van een provider: een partner (Auth0, Keycloak, Cognito, Okta) stuurt u JWT's ondertekend in RS256; u wilt bevestigen dat ze inderdaad van hem komen met zijn publieke sleutel.
  • Beveiligingsaudit: verifiëren dat een service van derden zijn tokens correct ondertekent met een robuust algoritme, en niet in HS256 met een zwak geheim.
  • Handmatige tests: verifiëren dat een door uw code gegenereerde JWT de verificatie passeert met de geleverde publieke sleutel.
  • Snelle verificatie van een ontvangen token: tijdens de integratie van een SSO of een partner-API, in enkele seconden verifiëren dat de handtekening/sleutel-keten werkt voordat u ook maar één regel code schrijft.

Hoe u de tool gebruikt

  1. Plak de volledige JWT (de drie delen gescheiden door punten).
  2. Geef de sleutel aan die geschikt is voor het algoritme van de header:
    • Voor HS256, HS384 of HS512, is de sleutel het geheim gedeelde tekenreeks met de uitgever. Het is een vrije tekenreeks, vaak opgeslagen in een omgevingsvariabele zoals JWT_SECRET.
    • Voor RS256, RS384 of RS512, is de sleutel de publieke sleutel in PEM-formaat, die begint met -----BEGIN PUBLIC KEY----- en eindigt met -----END PUBLIC KEY-----.
  3. Start de verificatie. De tool toont de status (geldig of ongeldig) en de gedecodeerde payload.

Veelvoorkomende valkuilen om te vermijden

  • Algoritme "none": de spec staat alg: none toe, wat betekent "geen handtekening". Een klassieke kwetsbaarheid bestaat uit het fabriceren van een token met deze header in de hoop dat de server het accepteert. Onze tool weigert systematisch tokens met alg: none.
  • HMAC vs RSA-verwarring (algorithm confusion): een aanvaller verandert het algoritme RS256 in HS256 en ondertekent de payload met de publieke RSA-sleutel gebruikt als HMAC-geheim. Als de server het algoritme niet controleert, accepteert hij het token. Vergrendel altijd het verwachte algoritme aan de serverkant.
  • Hard-coded HMAC-geheimen in de code: een in een Git-repository gecommit geheim maakt alle tokenvertrouwen ongeldig. Bewaar geheimen in omgevingsvariabelen of een applicatie-kluis.
  • Publieke sleutel vs privésleutel: om een in RSA of ECDSA ondertekende JWT te verifiëren, levert u de publieke sleutel, nooit de privé. De privé dient alleen om te ondertekenen en mag nooit uit de uitgever verlaten.
  • Vervaldatum genegeerd: een geldige handtekening op een verlopen token mag nooit worden geaccepteerd. Denk eraan om exp en nbf te verifiëren.
  • Niet-gecontroleerde audience: een token bestemd voor API A zou niet geaccepteerd mogen worden door API B. Verifieer de aud-claim.

Temporele claims: exp en nbf

Naast de handtekening moet een geldige JWT ook zijn temporele beperkingen respecteren:

  • exp (expiration): het token is niet meer geldig na deze datum.
  • nbf (not before): het token is nog niet geldig voor deze datum.

Onze tool signaleert expliciet wanneer een token verlopen is of nog niet geldig, zelfs als zijn handtekening correct is. Dat is belangrijk: een geldige handtekening op een verlopen token mag nooit worden geaccepteerd in productie.

Verschil met onze JWT decoder

Onze JWT decoder beperkt zich tot het decoderen van de header- en payload-delen om ze leesbaar te maken. Hij voert geen handtekeningverificatie uit en vraagt geen sleutel. Gebruik deze om snel de inhoud van een token te inspecteren. Gebruik de JWT verifier (deze pagina) zodra u moet bewijzen dat een token authentiek is. Om een ondertekende JWT voor testdoeleinden te fabriceren, gebruik onze JWT builder.

Veelgestelde vragen

Waarom RS256 in plaats van HS256?

Met HS256 delen de uitgever en de verificateur hetzelfde geheim: elke verificateur kan dus tokens uitgeven. Het is beheersbaar wanneer men beide uiteinden controleert. Zodra men spreekt over een unieke identiteitsprovider met meerdere consumerende services, schakelt men over naar RS256: de uitgever behoudt de privésleutel, men distribueert de publieke sleutel aan alle API's die moeten verifiëren. Geen enkele consumerende API kan dan tokens smeden.

Hoe haal ik de publieke sleutel van een identiteitsprovider (IdP) op?

De meeste IdP's stellen een gestandaardiseerde JWKS-endpoint beschikbaar (bijvoorbeeld https://voorbeeld.com/.well-known/jwks.json). Deze endpoint geeft een JSON terug met de actieve publieke sleutels. U kunt de JWK-entry die overeenkomt met de kid van de header van uw JWT converteren naar een PEM-sleutel via het openssl-commando of via een JWKS-bibliotheek van uw stack (bijvoorbeeld jose-jwt, jwks-rsa).

Wat te doen als de verificatie mislukt?

Verifieer eerst het algoritme: een in HS256 ondertekend token wordt niet geverifieerd met een RSA-sleutel, en omgekeerd. Verifieer vervolgens de sleutel: een teveel aan witruimte, een ontbrekend regeleinde in een PEM-sleutel, of een HMAC-geheim dat licht verschilt van die gebruikt door de uitgever volstaan om de verificatie te laten mislukken. Als de IdP een sleutelrotatie heeft uitgevoerd, kan uw kid verwijzen naar een sleutel die u niet meer hebt.

Wat is JWKS?

JWKS (JSON Web Key Set, RFC 7517) is een JSON-formaat dat een set publieke sleutels beschrijft. Elke sleutel wordt geïdentificeerd door een kid (key ID) en de te verifiëren JWT verwijst naar deze kid in zijn header. Het mechanisme stelt de IdP in staat om zijn sleutels te roteren zonder de verificateurs te breken: zij raadplegen gewoon de JWKS-endpoint om de sleutel op te halen die overeenkomt met de kid van het ontvangen token.

Hoe genereer ik een RSA-sleutelpaar om mijn JWT's te ondertekenen?

Met OpenSSL: openssl genrsa -out private.pem 2048 vervolgens openssl rsa -in private.pem -pubout -out public.pem. De privésleutel ondertekent aan de uitgeverskant, de publieke sleutel verifieert aan de consumentenkant. Voor nieuwe services, verkies 3072 of 4096 bits.

Moet de JWT versleuteld worden naast ondertekend (JWE)?

Een ondertekende JWT (JWS) garandeert de integriteit en authenticiteit, maar de payload blijft leesbaar voor iedereen die hem ophaalt. Als het token gevoelige gegevens bevat (interne identifiers, gedetailleerde rechten, persoonsgegevens), overweeg dan het JWE-formaat (JSON Web Encryption) dat de payload versleutelt naast deze te ondertekenen.

Voorbeeldverzoek

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

Invoerschema

Veld Type Vereist Standaard
token text
key text

Endpoints

  • GET https://cdrn.fr/api/v1/tools - toont alle beschikbare tools
  • GET https://cdrn.fr/api/v1/tools/jwt-verifier - geeft het schema van deze tool terug
  • POST https://cdrn.fr/api/v1/tools/jwt-verifier/execute - voert deze tool uit met een JSON-payload