JSON Web Token (JWT) im Detail

Keine Kommentare

JWT ist die Abkürzung für “JSON Web Token”, das für den Einsatz im Web konzipiert wurde. Typisches Einsatzgebiet für JWT ist die fortlaufende Authentifizierung bei SSO (“single sign-on”), JWT ist aber flexibel einsetzbar für alle Bereiche, in denen kompakte, signierte und u. U. verschlüsselte Informationen übertragen werden müssen. Dieser Artikel gibt einen Überblick über den Aufbau und die Nutzung von JWT.

Eine konkrete Implementierung gibt es beispielsweise bei Atlassian Connect. Die Cloud-Lösung für Produkte wie JIRA, Confluence, Bamboo und andere nutzt JWT zur Kommunikation mit Add-ons von Drittanbietern. JWT wird hier eingesetzt, um Requests zu authentifizieren und die Integrität der Anfrage sicherzustellen. Einen Überblick über Atlassian Connect bietet unser Artikel über die Sicherheit von Atlassian.

Aufbau eines JWT-Token

Das JWT ist ein einfacher String, der als Request-Parameter oder im Header übertragen wird. Ein JWT hat den folgenden Aufbau:

HEADER.PAYLOAD.SIGNATURE

Ein JWT-Token besteht also aus drei Teilen, die durch Punkte (.) voneinander getrennt sind. Hier sind beispielhafte Belegungen dieser Teile:

  • Header: “eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
  • Payload: “eyJpZCI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiTWFydGhhIFRlc3RlciJ9
  • Signatur: “AfF8fGzbhhpS9k-rgJt7RlZaUnP9phwmnPTku2fs4o0”

Der Header beschreibt den Signatur- und/oder Verschlüsselungsalgorithmus und den Token-Typ. Die Daten werden im JSON-Format abgelegt und Base64-kodiert. Das vorliegende Beispiel sieht im Klartext so aus:

{"alg":"HS256","typ":"JWT"}

Im Beispiel wurde die Payload des JWT mit HMAC SHA256 (abgekürzt “HS256”) signiert.

Als Payload wird das JSON-Objekt bezeichnet, das aus einer “beliebigen” Anzahl von Key/Value-Paaren besteht. Diese Key/Value-Paare werden ”Claims” genannt (siehe unten). Der Payload  wird ebenfalls Base64-kodiert. Im Beispiel hat der Payload folgenden Inhalt:

{ "id": "1234567890", "name": "Martha Tester" }

Das letzte Element ist die Signatur, die aus dem Header und der Payload berechnet wird. Der Algorithmus kann in Pseudocode wie folgt beschrieben werden:

content = base64UrlEncode(header) + "." + base64UrlEncode(payload);
signature = HMACSHA256(content, secret);

Auch die daraus entstehende Signatur wird ebenfalls Base64-kodiert und bildet den dritten Abschnitt des JWT.

Payload und Claims

Wie bereits erwähnt, enthält der Payload eine beliebige Anzahl von Key/Value-Paaren. Der Key wird in diesem Kontext als “Claim” bezeichnet. Prinzipiell darf der Payload beliebig viele Claims beinhalten. Natürlich wächst das JWT mit jedem Element und benötigt dann auch mehr Ressourcen bei der (De-)Kodierung. Es empfiehlt sich daher, die Informationen im JWT stark zu begrenzen.

Claims können in drei verschiedene Typen aufgeteilt werden: registrierte, öffentliche und private Claims.

Registrierte Claims

Es handelt sich hierbei um Keys, deren Zweck in einem Standard festgelegt ist. Wichtig: Die Spezifikation definiert, dass alle Claims optional sind! Applikationen können also frei wählen, ob sie diese Felder nutzen. Wenn sie genutzt werden, sind öffentliche Claims wie folgt zu nutzen (Auszug):

  • “iss” (Issuer): identifiziert die Einheit, die das JWT ausgegeben hat; Beispiel: die ID einer bestimmten JIRA-Applikation
  • “sub” (Subject): Dieses Feld wird dazu genutzt, den Nutzer, auf den sich eine Aktion bezieht, zu identifizieren; Beispiel: der Nutzer, der in JIRA eine Aktion ausgelöst hat
  • “aud” (Audience): identifiziert potenzielle Empfänger des JWT
  • “exp” (expiration time): der Zeitpunkt, zu dem das JWT-Token nicht mehr akzeptiert werden darf
  • “jti” (JWT ID): Dieser Wert ist dazu gedacht, Events zu markieren, die nur einmal verarbeitet werden sollen. Wie diese ID im konkreten Fall gespeichert und zur (In-)Validierung eines Events genutzt wird, ist die Aufgabe der Applikation selbst.

Weitere Claims sind im RFC 7519 beschrieben.

Öffentliche (“Public”) Claims

Diese Claims bezeichnen Key/Values, die zusätzlich zum Standard benutzt werden können. Um Kollisionen in der Semantik der Keys ausschließen zu können, sind diese Claims öffentlich registriert. Das Registrierungsverfahren ist in einem RFC 7519  beschrieben. Einen Überblick über öffentliche Claims gibt IANA.

Private Claims

Hierbei handelt es sich um Keys, die bei verschiedenen JWT-Nutzungen eine unterschiedliche Semantik aufweisen können. Die Keys sind für Parteien gedacht, die über JWT kommunizieren wollen und für ihren Anwendungsfall einen Key explizit vereinbaren wollen. Die Namen sind nicht öffentlich registriert (siehe auch IANA).

Vertraulichkeit und Datenintegrität

Das JWT basiert auf zwei weiteren Standards, die zur sicheren Kommunikation im Web gesetzt wurden. Dies ist zum einen JWS (JSON Web Signature), ein Schema, das die Signierung von Nachrichten regelt, zum anderen JWE-Schema (JSON Web Encryption), das zur Verschlüsselung von JWT genutzt wird. Je nach Sensibilität der Daten müssen eines oder beide Verfahren für das JWT umgesetzt werden.

Oliver Hoogvliet

Oliver arbeitet seit 20 Jahren in der Softwareentwicklung. Seine Begeisterung für die agile Softwareentwickung entwicklelte sich durch die Arbeit in unterschiedlichen Rollen in agilen Teams. Aktuell ist er als Senior IT Consultant bei der codecentric AG tätig. Seine Schwerpunktthemen sind agile Softwareentwicklung, agile Methodiken, Continuous Delivery, Spring Boot, Java, Groovy und DevOps.

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon

Kommentieren

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.