JSON Web Tokens erklärt: Claims, Signaturen und sichere Prüfung
Ein JSON Web Token, kurz JWT, ist ein kurzes Stück Text, das einige Angaben über einen Benutzer oder eine Anfrage enthält – wer es ausgestellt hat, um wen es geht, wann es abläuft – und dazu eine Signatur, mit der der Empfänger prüfen kann, dass niemand diese Angaben verändert hat. APIs akzeptieren JWTs als Access-Tokens, Anmeldesysteme stellen sie als ID-Tokens aus, und viele Web-Apps verwenden sie als Sitzungstokens. Dieser Ratgeber erklärt, was in einem JWT steckt, wie sich die Signaturalgorithmen unterscheiden, was ein Server prüfen muss, bevor er einem Token vertraut, welche Angriffe ausgelassene Prüfungen ausnutzen und wie Sie mit Ablauf und Speicherung umgehen.
Was ein JWT ist
Das Format ist in RFC 7519 definiert, das 2015 veröffentlicht wurde. Ein JWT ist eine Reihe von Claims – Aussagen wie „das Subjekt ist user-4821“ –, die als JSON kodiert und dann entweder signiert oder verschlüsselt werden. Fast jedes JWT im Einsatz ist signiert, und zwar als JSON Web Signature (JWS, RFC 7515): Jeder kann es lesen, aber ohne den Schlüssel kann niemand es unbemerkt verändern. Verschlüsselte JWTs (JWE, RFC 7516) verbergen zusätzlich den Inhalt und sind deutlich seltener.
Die JWTs, denen Sie am wahrscheinlichsten begegnen, sind in zwei Standards definiert. OpenID Connect, die Anmeldeschicht hinter Schaltflächen wie „Anmelden mit …“, stellt ein ID-Token aus, das ein signiertes JWT sein muss. Das JWT-Profil für Access-Tokens nach OAuth 2.0 (RFC 9068, 2021) legt fest, wie ein API-Access-Token aussieht, wenn es ein JWT ist; die Access-Tokens vieler Anbieter sind allerdings älter als dieses Profil und folgen ihm nicht genau.
Die drei Teile
Ein signiertes JWT besteht aus drei Stücken Base64URL-Text, die durch Punkte verbunden sind: Header, Payload und Signatur. Hier ein vollständiges Token, an den Punkten aufgeteilt:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9Header: {"alg":"HS256","typ":"JWT"} – der Signaturalgorithmus und der Tokentyp.eyJpc3MiOiJodHRwczovL2F1dGguZXhhbXBsZS5jb20iLCJzdWIiOiJ1c2VyLTQ4MjEiLCJhdWQiOiJodHRwczovL2FwaS5leGFtcGxlLmNvbSIsImlhdCI6MTc5MTk2ODQwMCwiZXhwIjoxNzkxOTY5MzAwLCJqdGkiOiJhOTFjMmU3ZiJ9Payload: Aussteller https://auth.example.com, Subjekt user-4821, Empfänger https://api.example.com, ausgestellt um 1791968400, läuft ab um 1791969300, ID a91c2e7f.yQ_-tR1KNYT8HL6voHLYDvp5GY6EWmR33VMZ8BbD1usSignatur: ein HMAC-SHA256 der ersten beiden Teile, erzeugt mit einem geheimen Schlüssel. Es handelt sich um Binärdaten, nicht um JSON.
Base64URL ist gewöhnliches Base64, bei dem zwei Zeichen ersetzt sind, damit das Ergebnis in URLs unbedenklich ist (- und _ statt + und /); in JWTs entfällt außerdem das Auffüllzeichen = am Ende. Es ist eine Kodierung, keine Verschlüsselung: Jeder kann die ersten beiden Teile wieder in JSON zurückverwandeln.
Die Signatur wird über den exakten Text von kodiertem Header und kodierter Payload berechnet, verbunden durch den Punkt dazwischen. Ändern Sie auch nur ein Zeichen in einem der beiden – setzen Sie den Ablaufzeitpunkt später an oder tragen Sie ein anderes Subjekt ein –, passt die Signatur nicht mehr.
Die Standard-Claims
RFC 7519 definiert sieben registrierte Claims. Im Basisstandard sind alle optional; die darauf aufbauenden Protokolle machen einige davon verpflichtend.
| Claim | Name | Bedeutung |
|---|---|---|
iss | Aussteller | Wer das Token erstellt und signiert hat, meist eine URL |
sub | Subjekt | Um wen es in dem Token geht, meist eine Benutzer-ID |
aud | Empfänger | Für wen das Token bestimmt ist; ein nicht aufgeführter Empfänger muss es ablehnen |
exp | Ablaufzeitpunkt | Ab diesem Zeitpunkt darf das Token nicht mehr akzeptiert werden |
nbf | Nicht vor | Vor diesem Zeitpunkt darf das Token nicht akzeptiert werden |
iat | Ausstellungszeitpunkt | Wann das Token erstellt wurde; daran lässt sich sein Alter ablesen |
jti | JWT-ID | Eine eindeutige Kennung, nützlich gegen Replay-Angriffe und für den Widerruf |
Die drei Zeit-Claims (exp, nbf und iat) sind Unix-Zeitstempel: die Anzahl der Sekunden, normalerweise ganzzahlig, seit dem 1. Januar 1970 UTC. Im Beispiel steht 1791968400 für den 14. Oktober 2026 um 09:00 Uhr UTC und 1791969300 für fünfzehn Minuten später. RFC 7519 erlaubt einem Server einen kleinen Spielraum für voneinander abweichende Uhren, „in der Regel nicht mehr als ein paar Minuten“.
Ein ID-Token nach OpenID Connect muss iss, sub, aud, exp und iat enthalten. Ein Access-Token nach RFC 9068 muss iss, exp, aud, sub, client_id, iat und jti enthalten und im Header den Typ at+jwt tragen. Alles Weitere in einer Payload – ein Name, eine E-Mail-Adresse, Rollen – legt die Anwendung fest.
Signaturalgorithmen
Der Wert alg im Header nennt den Algorithmus. Die Algorithmen lassen sich in zwei Gruppen einteilen: ein gemeinsames Geheimnis, bei dem derselbe Schlüssel signiert und prüft, und ein Schlüsselpaar, bei dem ein privater Schlüssel signiert und ein öffentlicher Schlüssel prüft.
| alg | Verfahren | Wer prüfen kann | Hinweise |
|---|---|---|---|
HS256 | HMAC mit SHA-256 und einem gemeinsamen Geheimnis | Jeder, der das Geheimnis kennt – und damit auch Tokens erstellen kann | Der Schlüssel muss mindestens 256 Bit lang sein (RFC 7518) und darf nie ein Passwort sein (RFC 8725). |
RS256 | RSA-Signatur mit SHA-256 | Jeder mit dem öffentlichen Schlüssel | RSA-Schlüssel mit mindestens 2048 Bit. Die empfohlene Standardwahl für ID-Tokens nach OpenID Connect. |
ES256 | ECDSA auf der Kurve P-256 mit SHA-256 | Jeder mit dem öffentlichen Schlüssel | Deutlich kürzere Schlüssel und Signaturen als bei RSA. |
Ed25519 | EdDSA mit dem Parametersatz Ed25519 | Jeder mit dem öffentlichen Schlüssel | Im Oktober 2025 registriert (RFC 9864); ersetzt den älteren, weniger spezifischen Bezeichner EdDSA, den viele Bibliotheken noch verwenden. |
none | Keine Signatur | Niemand: Das Token ist ungeschützt | Implementierungen dürfen es standardmäßig nicht akzeptieren (RFC 7518). |
HS256 eignet sich für einen einzelnen Dienst, der seine eigenen Tokens sowohl ausstellt als auch prüft. Wenn andere Dienste Tokens prüfen müssen – mehrere APIs oder Partner –, passt ein Schlüsselpaar besser: Diese erhalten nur den öffentlichen Schlüssel, mit dem sich keine Tokens erstellen lassen.
Dekodieren ist nicht Verifizieren
Jeder kann ein JWT mit beliebiger Payload schreiben; es zu dekodieren, wie es der Decoder von nTools tut, zeigt nur, was es behauptet. Ein Token beweist erst dann etwas, wenn der Server, der es empfängt, die folgenden Prüfungen vorgenommen hat. Sie beruhen auf RFC 7519 und RFC 8725, den Best Current Practices der IETF für JWTs:
- Legen Sie die zulässigen Algorithmen in der Serverkonfiguration fest und lehnen Sie alle anderen ab. Lassen Sie nie den alg-Wert im Header des Tokens bestimmen, wie es geprüft wird, und verwenden Sie jeden Schlüssel nur mit einem einzigen Algorithmus.
- Verifizieren Sie die Signatur mit dem Schlüssel, der zum erwarteten Aussteller gehört.
- Prüfen Sie, ob iss der Aussteller ist, dem Sie vertrauen, und ob aud Ihren Dienst nennt.
- Verlangen Sie, dass exp und die anderen Claims, auf die Ihr Dienst angewiesen ist, vorhanden sind, und prüfen Sie exp und nbf anhand der aktuellen Zeit mit höchstens ein paar Minuten Spielraum. Ein Token ohne exp würde sonst nie ablaufen.
- Wo ein Tokentyp definiert ist, prüfen Sie typ – zum Beispiel at+jwt bei Access-Tokens –, damit sich eine Art von Token nicht als eine andere ausgeben lässt.
- Behandeln Sie die Header-Felder kid, jku und x5u als nicht vertrauenswürdige Eingaben: Schlagen Sie kid in Ihrer eigenen Schlüsselliste nach, und beziehen Sie Schlüssel nur aus dem konfigurierten Schlüsselsatz des Ausstellers oder von Adressen, die Sie vorab zugelassen haben.
In der Praxis gehören diese Prüfungen in eine gepflegte JWT-Bibliothek, die mit dem erwarteten Aussteller, Empfänger und den erwarteten Algorithmen konfiguriert ist, und nicht in selbst geschriebenen Code.
Die klassischen Angriffe
Die meisten JWT-Schwachstellen sind keine Schwächen der Kryptografie, sondern Prüfungen, die ein Server ausgelassen hat. RFC 8725 beschreibt die folgenden:
- alg none: Der Angreifer ändert den Header auf none und löscht die Signatur. Ein Server, der dem Header vertraut, akzeptiert ein Token, das jeder hätte schreiben können.
- Schlüsselverwechslung: Ein Server erwartet RS256, der Angreifer schickt aber ein als HS256 gekennzeichnetes Token, signiert mit dem öffentlichen Schlüssel des Servers, als wäre dieser ein HMAC-Geheimnis. Eine Bibliothek, die den Algorithmus aus dem Header übernimmt, prüft es dann mit genau diesem öffentlichen Schlüssel – und die Prüfung gelingt.
- Schwache Geheimnisse: Ein HS256-Geheimnis, das kurz oder ein Passwort ist, lässt sich offline durch Raten ermitteln – anhand eines einzigen abgefangenen Tokens und ohne jeden Kontakt zum Server. Mit dem Geheimnis kann der Angreifer beliebige Tokens signieren.
- Substitution: Ein gültiges Token, das für einen Dienst oder einen Zweck ausgestellt wurde, wird einem anderen vorgelegt – ein ID-Token als Access-Token oder ein Token für eine API bei einer anderen.
Die Prüfungen aus dem vorigen Abschnitt verhindern jeden dieser Angriffe: Eine feste Liste von Algorithmen, bei der jeder Schlüssel an einen einzigen Algorithmus gebunden ist, stoppt die ersten beiden, ein zufälliges Geheimnis von mindestens 256 Bit den dritten und die Prüfung von aud und typ den letzten.
Die Payload ist öffentlich
Eine Signatur schützt vor Änderungen, nicht vor dem Mitlesen. Tokens werden in Request-Headern übertragen (und manchmal, unklugerweise, in URLs) und landen in Logs, im Browserspeicher und in Referer-Headern, und jeder, der eines zu sehen bekommt, kann es dekodieren. Passwörter, Geheimnisse und personenbezogene Daten, die der Empfänger nicht braucht, gehören nicht in eine Payload.
Wenn Claims mit dem Token übertragen werden und dennoch vertraulich bleiben müssen, kann das Token als JWE verschlüsselt werden, das aus fünf statt drei Teilen besteht. Die von OWASP vorgeschlagene Alternative ist oft einfacher: Die Daten bleiben auf dem Server, und der Client erhält ein opakes Referenz-Token, das für sich genommen nichts bedeutet.
Ablauf, Widerruf und Speicherung
Ein signiertes JWT ist bis exp gültig, wo auch immer es sich befindet: Der Server muss es nirgends nachschlagen – das macht JWTs schnell prüfbar und ist zugleich der Grund, warum ein gestohlenes Token weiter funktioniert. Kurze Ablaufzeiten begrenzen den Schaden. Um ein Token früher zurückzuziehen, muss der Server doch einen Zustand speichern – OWASP beschreibt eine Sperrliste, deren Einträge über die Claims jti und iss zugeordnet werden; ein Eintrag kann entfernt werden, sobald der exp-Zeitpunkt des Tokens verstrichen ist.
Anwendungen, die längere Sitzungen brauchen, kombinieren ein kurzlebiges Access-Token mit einem Refresh-Token, mit dem neue Access-Tokens abgerufen werden. Die Sicherheitsempfehlungen für OAuth 2.0 (RFC 9700, Januar 2025) verlangen, dass Refresh-Tokens, die an öffentliche Clients ausgegeben werden – typischerweise Browser- und Mobil-Apps, die kein Geheimnis bewahren können –, entweder an den Absender gebunden sind, also kryptografisch mit diesem Client verknüpft, oder rotiert werden: Bei jeder Verwendung werden sie durch ein neues ersetzt, und das alte wird ungültig.
Im Browser rät OWASP davon ab, Sitzungskennungen in localStorage abzulegen, weil eine einzige Cross-Site-Scripting-Lücke alles auslesen kann, was dort gespeichert ist. Ein mit HttpOnly gekennzeichnetes Cookie kann von JavaScript überhaupt nicht gelesen werden; es sollte aber zusätzlich mit Secure und SameSite gekennzeichnet sein, und ein in die Seite eingeschleustes Skript kann trotzdem Anfragen senden, bei denen das Cookie mitgeschickt wird.
Häufige Fragen
Ist ein JWT verschlüsselt?
Meist nicht. Die meisten JWTs sind signiert, und Header und Payload sind nur Base64URL-kodiert, sodass jeder, der das Token hat, sie lesen kann. Nur ein JWE mit seinen fünf Teilen verbirgt seinen Inhalt.
Kann ich ein JWT ohne den Schlüssel lesen?
Ja, sofern es kein verschlüsseltes JWE ist. Bei einem signierten JWT brauchen Sie den Schlüssel, um die Signatur zu erzeugen oder zu verifizieren, nicht aber, um Header und Payload zu lesen.
Wie lange sollte ein JWT gültig sein?
Die Standards nennen keinen einheitlichen Wert. Der übliche Rat lautet: so kurz, wie es die Anwendung zulässt, mit Refresh-Tokens für längere Sitzungen; ein verlorenes Token ist dann nur kurze Zeit von Nutzen.
Sollte ich JWTs für Website-Sitzungen verwenden?
Nicht unbedingt. Eine klassische Sitzungs-ID in einem Cookie lässt sich auf dem Server sofort widerrufen; ein JWT erspart bei jeder Anfrage ein Nachschlagen, lässt sich aber vor seinem Ablauf nicht zurückziehen, ohne zusätzlichen Zustand zu speichern.
Ist es sicher, ein Token in den Decoder von nTools einzufügen?
Das Token wird in Ihrem Browser dekodiert und nirgendwohin gesendet. Verwenden Sie trotzdem lieber ein abgelaufenes oder ein Test-Token: Ein noch gültiges Token ist ein Zugangsnachweis.
Zurück in der Reihe ← Hashfunktionen erklärt: SHA-256, Prüfsummen und Passwort-Hashing
Quellen
- RFC 7519 — JSON Web Token (JWT) (May 2015)
- RFC 7515 — JSON Web Signature (JWS) (May 2015)
- RFC 7516 — JSON Web Encryption (JWE) (May 2015)
- RFC 7518 — JSON Web Algorithms (JWA) (May 2015)
- RFC 8725 — JSON Web Token Best Current Practices (February 2020)
- RFC 9068 — JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens (October 2021)
- RFC 9700 — Best Current Practice for OAuth 2.0 Security (January 2025)
- RFC 9864 — Fully-Specified Algorithms for JOSE and COSE (October 2025)
- OpenID Connect Core 1.0 incorporating errata set 2 (December 2023)
- OWASP — JSON Web Token Cheat Sheet
- OWASP — HTML5 Security Cheat Sheet: Local Storage
Weitere Ratgeber
- IP-Adressen erklärt: IPv4, IPv6 und die reservierten Bereiche
- Subnetze und CIDR erklärt: Präfixe, Masken und nutzbare Hosts
- DNS-Einträge erklärt: A, AAAA, CNAME, MX, TXT und NS
- Ist eine Website down oder liegt es an dir? So prüfst du es Schritt für Schritt
- HTTP-Statuscodes und Cloudflare-Fehler: was 403, 404, 429, 500, 503 und 521 bedeuten
- Unix-Zeitstempel und Zeitzonen erklärt
- Mit Datumsangaben rechnen: Tage zwischen zwei Daten, Schaltjahre und ISO-Wochen
- Bildformate erklärt: JPEG, PNG, WebP, AVIF und HEIC
- Passwortstärke erklärt: Länge, Entropie und Passphrasen
- Hashfunktionen erklärt: SHA-256, Prüfsummen und Passwort-Hashing
- UUIDs erklärt: v4, v7 und die Wahl der richtigen Version
- QR-Codes erklärt: Kapazität, Fehlerkorrektur und Druckgröße
- Prozente und Mehrwertsteuer erklärt: aufschlagen, herausrechnen, kombinieren
- Häufige JSON-Fehler und wie man sie behebt
- PDFs im Browser bearbeiten: Was beim Zusammenfügen, Teilen und Umwandeln erhalten bleibt