Wat is JSON Web Token (JWT)?
Krijg een helder begrip van de basisprincipes van JSON Web Token (JWT) in 5 minuten.
JSON Web Token (JWT) wordt veel gebruikt in moderne webapplicaties en open standaarden zoals OpenID Connect, voor het vergemakkelijken van authenticatie en autorisatie. Hoewel de officiële RFC 7519 een essentieel referentiepunt is, kan het voor beginners moeilijk te begrijpen zijn. In dit artikel richten we ons op de kernconcepten van JWT en presenteren we ze in duidelijke taal met voorbeelden.
Waarom hebben we JWT nodig?
Tegenwoordig is het vrij gebruikelijk om JSON te gebruiken om gegevens tussen twee partijen uit te wisselen. Beschouw een JSON-object dat een gebruiker vertegenwoordigt:
sub
is een afkorting voor "subject", wat een standaardclaim in OpenID Connect is om de gebruikersidentificatie (user ID) te vertegenwoordigen.
Hoe kunnen we de integriteit van dit JSON-object garanderen? Met andere woorden, hoe kunnen we ervoor zorgen dat de gegevens niet zijn gewijzigd tijdens de overdracht? Een veelvoorkomende oplossing is het gebruik van digitale handtekeningen. Bijvoorbeeld, we kunnen public-key cryptografie gebruiken: de server ondertekent het JSON-object met zijn privésleutel en de client kan de handtekening verifiëren met de publieke sleutel van de server.
Kortom, JWT biedt een gestandaardiseerde benadering voor het weergeven van het JSON-object en zijn handtekening.
Het formaat van JWT
Aangezien er veel algoritmen zijn voor het maken van digitale handtekeningen, is het noodzakelijk om het gebruikte algoritme voor JWT-ondertekening te specificeren. Dit wordt bereikt door een JSON-object te construeren:
alg
is een afkorting voor "algorithm", entyp
is een afkorting voor "type".
Typisch wordt typ
ingesteld op JWT
in hoofdletters. Voor ons voorbeeld is alg
HS256
, wat staat voor HMAC-SHA256 (we zullen het zo uitleggen), en geeft aan dat we dit algoritme gebruiken om de handtekening te maken.
Nu hebben we alle ingrediënten voor een JWT:
- Header JSON: Algoritme en type
- Payload JSON: De daadwerkelijke gegevens
- Signature: De handtekening die de header en payload omvat
Echter, bepaalde tekens zoals spaties en regeleindes zijn niet vriendelijk voor netwerkoverdracht. Daarom moeten de header en payload Base64URL-gecodeerd zijn. De typische JWT ziet er als volgt uit:
De
.
dient als scheidingsteken.
Laten we alles samenbrengen en een JWT maken:
Header
JSON: {"alg":"HS256","typ":"JWT"}
Base64URL gecodeerd: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload
JSON: {"sub":"foo","name":"John Doe"}
Base64URL gecodeerd: eyJzdWIiOiJmb28iLCJuYW1lIjoiSm9obiBEb2UifQ
Signature
In HMAC-SHA256 wordt de handtekening gemaakt met een geheim:
Bijvoorbeeld, met het geheim als some-great-secret
, wordt de handtekening: XM-XSs2Lmp76IcTQ7tVdFcZzN4W_WcoKMNANp925Q9g
.
JWT
De uiteindelijke JWT is:
Deze geldige JWT kan worden geverifieerd door elke partij die het geheim bezit.
Kies het ondertekeningsalgoritme
Zoals eerder vermeld, zijn er verschillende algoritmen om digitale handtekeningen te maken. We gebruikten HS256
als een voorbeeld, maar het is mogelijk niet sterk genoeg omdat het geheim moet worden gedeeld tussen de partijen (bijv. de client en de server).
In realistische scenario's kunnen clients openbare applicaties zijn, zoals React-apps die het geheim niet veilig kunnen houden. Daarom is de geprefereerde benadering het gebruik van public-key cryptografie (d.w.z. asymmetrische cryptografie) voor het ondertekenen van de JWT. Laten we beginnen met het meest populaire algoritme: RSA.
RSA
RSA, een asymmetrisch algoritme, gebruikt een paar sleutels: een publieke sleutel en een privésleutel. De publieke sleutel wordt gebruikt om de handtekening te verifiëren, terwijl de privésleutel wordt gebruikt voor ondertekening.
De header JSON voor RSA ziet er als volgt uit:
RS256
staat voor RSA-SHA256, wat betekent dat de handtekening is gemaakt met het RSA-algoritme en SHA256-hashfunctie. Je kunt ookRS384
enRS512
gebruiken om handtekeningen te maken met SHA384 en SHA512-hashfuncties, respectievelijk.
De handtekening wordt gemaakt met de privésleutel:
Opnieuw kunnen we deze onderdelen samenstellen om een JWT te maken, en de uiteindelijke JWT ziet er als volgt uit:
Nu kan de client de handtekening verifiëren zonder de privésleutel te kennen.
ECDSA
Hoewel RSA veel wordt gebruikt, heeft het last van grotere handtekeningen, soms groter dan de gecombineerde grootte van de header en payload. Het Elliptic Curve Digital Signature Algorithm (ECDSA) is een ander asymmetrisch algoritme dat compactere handtekeningen kan maken en meer prestaties biedt.
Om een privésleutel te genereren voor ECDSA, moeten we een curve kiezen. Dit valt buiten de reikwijdte van dit artikel, maar je kunt meer informatie vinden hier.
De header JSON voor ECDSA ziet er als volgt uit:
ES256
staat voor ECDSA-SHA256, wat betekent dat de handtekening is gemaakt met het ECDSA-algoritme en SHA256-hashfunctie. Je kunt ookES384
enES512
gebruiken om handtekeningen te maken met SHA384 en SHA512-hashfuncties, respectievelijk.
De handtekening wordt gemaakt met de privésleutel:
De uiteindelijke JWT behoudt dezelfde structuur als RSA maar met een aanzienlijk kortere handtekening:
Verifieer de JWT
Het verifiëren van een JWT is eenvoudig als het omgekeerde proces van het maken van een JWT:
- Splits de JWT in drie delen (header, payload en handtekening) met behulp van de
.
scheidingsteken. - Decodeer de header en payload met Base64URL.
- Verifieer de handtekening met het algoritme dat in de header is gespecificeerd en de publieke sleutel (voor asymmetrische algoritmen).
Er zijn veel bibliotheken beschikbaar die kunnen helpen bij het verifiëren van JWT, zoals jose voor Node.js en webbrowsers.
Conclusie
In dit artikel hebben we kort de kernconcepten van JWT uitgelegd, samen met het overzicht over hoe het te maken en te verifiëren. Veel details blijven onverklaard, en we zullen ze in toekomstige artikelen behandelen.
Logto maakt gebruik van open standaarden zoals JWT en OpenID Connect om je apps en API's te beveiligen met vereenvoudigde workflows voor elke ontwikkelaar. Als je geïnteresseerd bent, kun je het gratis proberen (geen creditcard vereist).