Was steckt in einem JWT, und warum Dekodieren nicht Prüfen ist
Ein JSON Web Token (JWT) besteht aus drei durch Punkte verbundenen Textteilen: einem Header, einer Payload und einer Signatur. Die ersten beiden sind nur kodiert, nicht verschlüsselt, daher kann jeder, der das Token hat, sie lesen. Die Signatur ermöglicht einem Server zu prüfen, dass ein vertrauenswürdiger Aussteller das Token erstellt hat und niemand es verändert hat. Ein Token zu dekodieren zeigt dir, was darin steht. Erst das Verifizieren zeigt dir, ob du ihm glauben solltest.
JWT-DecoderToken abgelaufen, oder ist er gültig?Kostenlos loslegenDie drei Teile
Ein Token sieht so aus: header.payload.signature. Der erste Teil des bekannten Beispieltokens von jwt.io lautet:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Jeder der ersten beiden Teile ist JSON, das in base64url umgewandelt wurde, eine Textform, die sich sicher in URLs verwenden lässt. Der erste Teil dekodiert zu:
{"alg":"HS256","typ":"JWT"}
Die Payload desselben Beispiels dekodiert zu:
{"sub":"1234567890","name":"John Doe","iat":1516239022}
Die Payload enthält die Claims, also Aussagen über den Benutzer oder die Sitzung. Die Signatur wird aus den ersten beiden Teilen und einem Schlüssel berechnet, daher passt sie nicht mehr, sobald sich auch nur ein Zeichen ändert. base64url lässt sich ohne Schlüssel umkehren, deshalb gehören weder Passwörter noch private Schlüssel oder personenbezogene Daten in eine Payload.
Registrierte Claims
RFC 7519, der Standard für JWTs, reserviert einige kurze Claim-Namen:
iss(issuer): wer das Token erstellt hat.sub(subject): auf wen sich das Token bezieht, meist eine Benutzer-ID.aud(audience): der Dienst, für den das Token bestimmt ist.exp(expiration time): der Zeitpunkt, ab dem das Token ungültig ist.nbf(not before): der früheste Zeitpunkt, zu dem das Token gültig ist.iat(issued at): wann das Token erstellt wurde.
Zeitangaben sind Sekunden seit dem 1. Januar 1970 UTC, die sogenannte Unix-Zeit. Das Beispiel hat kein exp, laut Standard läuft es also nie ab. Ein echtes Token sollte eines haben. Andere Namen, etwa role oder email, gehören zur Anwendung.
Dekodieren ist nicht Verifizieren
Beim Dekodieren wird das Token an den Punkten getrennt, base64url umgekehrt und das JSON gelesen. Das zeigt, was das Token behauptet, und dasselbe gilt für ein gefälschtes Token, denn jeder kann beliebige Claims mit einer beliebigen Signatur schreiben.
Beim Verifizieren wird die Signatur mit dem richtigen Schlüssel neu berechnet und geprüft, ob sie übereinstimmt. Außerdem wird kontrolliert, ob exp und nbf die aktuelle Zeit einschließen und ob iss und aud die Werte sind, die der Dienst erwartet. Eine App, die einen role-Claim liest, ohne zu verifizieren, vertraut jedem, der das Token geschrieben hat. Das ist ein häufiger Fehler.
HS256, RS256 und ES256
Der Wert alg nennt das Verfahren. Drei sind verbreitet:
- HS256 ist HMAC mit SHA-256. Ein gemeinsames Geheimnis signiert und verifiziert, deshalb muss das Geheimnis auf dem Server bleiben, der die Tokens ausstellt.
- RS256 ist eine RSA-Signatur mit SHA-256. Der Aussteller signiert mit einem privaten Schlüssel, und jeder mit dem öffentlichen Schlüssel kann prüfen. Andere Dienste können Tokens prüfen, ohne sie erstellen zu können.
- ES256 ist eine ECDSA-Signatur mit der Kurve P-256 und SHA-256. Sie funktioniert wie RS256, mit kleineren Schlüsseln und Signaturen.
Verwende HS256, wenn ein einziger Dienst seine Tokens sowohl ausstellt als auch prüft. Verwende RS256 oder ES256, wenn andere Dienste Tokens prüfen müssen, die sie nicht selbst ausgestellt haben.
Probleme durch Vertrauen in den Header
Der Header wird von demjenigen geschrieben, der das Token schickt. Der Prüfer darf ihm daher nicht erlauben, die Regeln festzulegen.
alg: none. Ein Token ohne Signatur kann"alg":"none"angeben. Manche Bibliotheken haben solche Tokens früher akzeptiert und die Prüfung übersprungen. Lege die erlaubten Algorithmen in deinem eigenen Code fest und übernimm sie niemals aus dem Token.- Algorithmus-Verwechslung. Ein Server erwartet RS256 und kennt einen öffentlichen Schlüssel. Ein Angreifer schickt ein HS256-Token, das mit diesem öffentlichen Schlüssel als HMAC-Geheimnis signiert ist. Ein Prüfer, der jeden Algorithmus akzeptiert, den der Header nennt, nimmt es an. Bindet jeden Schlüssel an genau einen Algorithmus.
- Schwache Geheimnisse. Der Angreifer hat Header, Payload und Signatur und kann mögliche Geheimnisse offline ausprobieren. Ein kurzes Geheimnis oder ein gängiges Wort fällt auf so einer Liste schnell. RFC 7518 verlangt, dass ein HS256-Schlüssel mindestens 256 Bit lang und zufällig ist.
Ein Produktionstoken auf einer Website einfügen
Ein gültiges, nicht abgelaufenes Token funktioniert für jeden, der es besitzt, bis es abläuft. Behandle es wie ein Passwort. Bevor du eines auf einer Seite einfügst, finde heraus, ob die Seite es an einen Server schickt. Ein Werkzeug, das vollständig im Browser-Tab läuft, braucht das nicht. Du kannst jede Seite prüfen, indem du ihre Netzwerkanfragen in den Entwicklertools des Browsers beobachtest.
Tokens lassen sich meist nicht vor Ablauf widerrufen, außer der Server führt eine Liste. Wenn ein gültiges Token durchgesickert ist, bitte den Dienst, die Sitzung zu widerrufen oder die Schlüssel zu erneuern. Verwende nach Möglichkeit für die Fehlersuche ein Token aus der Testumgebung. Der JWT-Decoder liest die drei Teile in deinem Browser-Tab, und nichts, was du einfügst, wird irgendwohin gesendet.
Webhooks: dieselbe Idee mit einem gemeinsamen Geheimnis
Die meisten Webhook-Anbieter senden einen HMAC des Anfragekörpers, berechnet mit einem Geheimnis, das du mit ihnen teilst, in einem Header. Dein Empfänger berechnet denselben HMAC und vergleicht beide Werte. Häufige Fehler sind klein. Das JSON wird vor dem Hashen neu formatiert, sodass sich die Bytes ändern. Das Test-Geheimnis wird gegen Live-Traffic verwendet. Oder die Signaturen werden mit einem gewöhnlichen Stringvergleich geprüft, der Informationen über die Rechenzeit preisgeben kann. Verwende einen zeitkonstanten Vergleich.
Der Webhook-Signatur-Prüfer berechnet die Signatur aus dem Geheimnis und dem Körper, die du einfügst, für GitHub, Stripe, Slack, Shopify oder jedes andere HMAC-Schema, sodass du siehst, ob beide Werte übereinstimmen.
Kurze Antworten
Ist ein JWT verschlüsselt?
Nein. Ein Standard-JWT ist signiert, und jeder kann seinen Header und seine Payload lesen. Nur die Signatur schützt es vor Veränderungen.
Was passiert, wenn ich die Payload bearbeite?
Die Signatur passt nicht mehr, daher lehnt ein prüfender Server das Token ab. Das Lesen der Claims prüft die Signatur nicht, deshalb zeigt der Decoder trotzdem deine bearbeitete Version an.
Mit KI-Unterstützung aus dem Englisches Original übersetzt.
Kommentare
Noch keine Kommentare. Schreib den ersten.


