HandyTools Hub

← Alle Anleitungen

JWT erklärt: Die dreiteilige Struktur, was Signieren beweist und die klassischen Fehler

2026-08-06

Untersuchen Sie die Anfrage-Header irgendeiner App mit Login-Flow, und Sie finden fast sicher etwas wie Authorization: Bearer eyJhbGciOi... — das ist ein JWT (JSON Web Token). Es ist zum Standard-Credential-Format für entkoppelte Frontends und APIs geworden: Der Server gibt es einmal aus, der Client sendet es bei jeder Anfrage, und der Server kann „wer du bist“ bestätigen, ohne eine Datenbank zu berühren. Aber JWTs sind auch ein Hort von Missverständnissen. Menschen stopfen Geheimnisse hinein, als wären sie verschlüsselte Container, oder dekodieren sie und vertrauen dem Inhalt ohne Signaturprüfung — beides hervorragende Wege, einen Sicherheitsvorfall auszuliefern. Diese Anleitung geht die Struktur durch, was Signieren tatsächlich garantiert, und die klassischen Fallen.

Die drei Teile: Header.Payload.Signature

Ein JWT besteht immer aus drei durch Punkte verbundenen Segmenten:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NSIsImlhdCI6MTc1NDQ2NzIwMCwiZXhwIjoxNzU0NDcwODAwfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

Teil eins ist der Header, der den Tokentyp und den Signaturalgorithmus deklariert. Dekodiert ist es nur JSON:

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

Teil zwei ist der Payload, der die eigentlichen „Claims“ trägt — User-ID, Ausstellungszeit, Ablauf und so weiter:

{"sub": "12345", "iat": 1754467200, "exp": 1754470800}

Teil drei ist die Signatur über die ersten beiden Teile. Für HS256 berechnet der Signierer HMAC-SHA256 über header + "." + payload mit einem geheimen Schlüssel und hängt das Ergebnis an. Die Signatur existiert, um Manipulation zu erkennen: Ändern Sie ein einziges Zeichen im Payload, und die Signaturprüfung scheitert.

Alle drei Segmente sind Base64URL-kodiert, nicht einfaches Base64. Base64URL tauscht die +- und /-Zeichen von Standard-Base64 gegen - und _ und lässt das abschließende =-Padding weg — das macht das Token sicher für URLs und Header. Wollen Sie die Kodierungsregeln in Aktion sehen, kodieren Sie ein dekodiertes JSON-Fragment mit dem Base64-Encoder/Decoder neu und vergleichen Sie. Im Alltag ist der erste Griff bei jedem rätselhaften Token, es in den JWT-Decoder einzufügen, der die drei Teile trennt und das JSON sofort hübsch druckt.

Signieren beweist Integrität, nicht Vertraulichkeit

Das ist das Einzige, was Sie über JWTs unbedingt verinnerlichen müssen: Eine Signatur ist keine Verschlüsselung. Der Payload ist lediglich Base64URL-kodiertes JSON. Jeder, der das Token hält, kann es dekodieren — kein Schlüssel nötig. Kodierung ändert die Darstellung, nicht die Lesbarkeit; eyJzdWIiOiIxMjM0NSJ9 zurück in {"sub":"12345"} zu verwandeln ist ein Partytrick, kein Privileg.

Was die Signatur tatsächlich garantiert, ist Integrität und Authentizität:

  • Der Inhalt wurde seit der Ausstellung nicht verändert (jede Manipulation bricht die Signaturprüfung).
  • Das Token wurde wirklich von demjenigen ausgegeben, der den Signaturschlüssel hält (angenommen, der Schlüssel ist nicht geleakt).

Das korrekte Denkmodell ist also: Ein JWT ist ein manipulationssichtbarer Umschlag mit transparenten Wänden. User-IDs, Rollen, Berechtigungs-Scopes und Ablaufzeiten gehören hinein. Passwörter, Telefonnummern, Ausweisnummern und Geheimnisse auf keinen Fall. Braucht der Inhalt wirklich Vertraulichkeit, halten Sie ihn entweder ganz aus dem Token heraus oder nutzen JWE (verschlüsselte Tokens) — verlassen Sie sich nicht auf „niemand kann dieses Kauderwelsch lesen“. Das Kauderwelsch dekodiert in Millisekunden.

HS256 vs. RS256: symmetrisch und asymmetrisch

Das alg-Feld im Header benennt den Signaturalgorithmus. Zwei dominieren in der Praxis.

HS256 ist HMAC-SHA256, ein symmetrischer Algorithmus: Derselbe geteilte Schlüssel wird zum Signieren und zum Verifizieren genutzt. Der Aussteller berechnet ein HMAC mit dem Schlüssel; der Verifizierer berechnet es mit demselben Schlüssel neu und vergleicht. Es ist einfach und schnell und eine gute Wahl für ein einzelnes in sich geschlossenes System, in dem nur Ihr eigenes Backend den Schlüssel je sieht. Der Haken: Wer ein Token verifizieren kann, kann auch eines fälschen, jede Partei mit dem Schlüssel ist also ein potenzielles Leck. Wollen Sie HMAC in Aktion sehen, schicken Sie etwas Text als HMAC-SHA256 durch den Hash-Generator — ändern Sie den Schlüssel, und die Ausgabe ändert sich vollständig.

RS256 ist RSA, ein asymmetrischer Algorithmus: Der Aussteller signiert mit einem privaten Schlüssel, und Verifizierer prüfen die Signatur mit dem entsprechenden öffentlichen Schlüssel. Der öffentliche Schlüssel kann frei verteilt werden — viele Identity-Provider veröffentlichen ihren unter /.well-known/jwks.json —, sodass jeder Dienst Tokens verifizieren kann, während nur der Halter des privaten Schlüssels neue prägen kann. Das ist ein großer Gewinn in Multi-Service-Architekturen: Gateways und Dritte verifizieren mit dem öffentlichen Schlüssel, und der private Schlüssel verlässt nie den Aussteller.

Die Faustregel ist einfach: Ein System, Schlüssel verlässt nie das Haus — HS256; mehrere Parteien verifizieren oder Tokens überqueren Vertrauensgrenzen — RS256.

Gängige Claims: iss, sub, exp, iat

Die JWT-Spezifikation (RFC 7519) reserviert eine Handvoll Standard-Claims, alle im Payload:

{
  "iss": "https://auth.example.com",
  "sub": "user-12345",
  "iat": 1754467200,
  "exp": 1754470800
}
  • iss (Issuer): wer das Token ausstellte, typischerweise ein Identifikator oder eine URL für den Auth-Dienst. Verifizierer nutzen es, um zu bestätigen, dass das Token von einem Dienst kommt, dem sie vertrauen.
  • sub (Subject): wen das Token repräsentiert — meist eine User-ID.
  • iat (Issued At): wann das Token ausgestellt wurde, als Unix-Zeitstempel auf Sekundenebene.
  • exp (Expiration Time): wann das Token ungültig wird, ebenfalls ein Sekunden-Zeitstempel. Sobald die aktuelle Zeit exp überschreitet, müssen Verifizierer das Token ablehnen. Im obigen Beispiel lebt das Token genau eine Stunde.

Diese Namen sind reserviert — legen Sie eigene Daten (Rollen, Anzeigenamen, Feature-Flags) unter eigenen Schlüsseln ab, statt die Standardnamen umzuwidmen. Zwei weitere sind wissenswert: nbf (Not Before), das die Gültigkeit bis zu einer Zeit verzögert, und aud (Audience), das den Dienst benennt, für den ein Token gedacht ist — praktisch, wenn Tokens zwischen Microservices fließen.

Vier klassische Fehler

1. Geheimnisse in den Payload stecken. Wie oben behandelt: Der Payload ist weltlesbar. Passwort-Hashes, Kartennummern und „interne Notizen“ sind alle schon in JWTs gelandet und dann in Breach-Reports. Fragen Sie sich vor dem Schreiben eines Felds: Würde ich das auf eine Plakatwand drucken wollen?

2. Dekodieren ohne Verifizieren. Dekodieren ist keine Verifikation. Jeder kann ein Token Base64URL-dekodieren; dem Payload ohne Signaturprüfung zu vertrauen ist wie einer Notiz ohne Wasserzeichen zu vertrauen — ein Angreifer kann einfach sein eigenes Token mit sub: admin prägen. Die korrekte Reihenfolge ist: Signatur verifizieren → prüfen, dass alg der erwartete Algorithmus ist → exp/nbf/iss/aud validieren → und erst dann den Payload lesen. Der JWT-Decoder ist zum Ansehen des Inhalts; Produktionscode muss Signaturen verifizieren.

3. Die alg=none-Saga. Die JWT-Spezifikation erlaubt alg: "none" — ein unsigniertes Token für Fälle, in denen Sicherheit durch einen anderen Kanal garantiert wird. Frühe Versionen mehrerer JWT-Bibliotheken akzeptierten none standardmäßig, sodass Angreifer den Header zu {"alg":"none"} umschreiben, die Signatur entfernen und alles fälschen konnten. Ein verwandter Angriff stufte RS256-Tokens auf HS256 herab und nutzte den öffentlichen Schlüssel (der öffentlich ist!) als HMAC-Geheimnis. Die Nachwirkungen sind heute in jede ernsthafte Bibliothek eingebacken: Sie müssen die akzeptierten Algorithmen ausdrücklich festnageln, statt zu vertrauen, was das Token deklariert. Behandeln Sie das als harte Regel.

4. Langlebige Tokens ohne Widerrufspfad. JWTs Zustandslosigkeit ist ein zweischneidiges Schwert: Der Server speichert nach der Ausstellung nichts, was bedeutet, dass ein Token früh zu widerrufen wirklich schwer ist. Ein geleaktes Access-Token, das 30 Tage gültig ist, kauft einem Angreifer 30 Tage. Die übliche Abhilfe sind kurzlebige Access-Tokens (Minuten bis Stunden) gepaart mit langlebigen Refresh-Tokens, die serverseitig leben und widerrufen werden können; Hochsicherheitssysteme ergänzen eine Blacklist oder eine Token-Version pro Nutzer. Setzen Sie exp nie auf ein Jahr, nur um Refresh-Aufrufe zu vermeiden.

Abgelaufene und ungültige Tokens debuggen

Wenn die Produktion Ihnen ein 401 Invalid Token reicht, findet diese Reihenfolge die Ursache am schnellsten:

  1. Dekodieren und prüfen. Fügen Sie das Token in den JWT-Decoder ein und bestätigen Sie, dass alle drei Segmente existieren und der Payload gültiges JSON ist. Ein Token mit zwei Segmenten oder ohne Punkte wurde wahrscheinlich abgeschnitten oder unvollständig kopiert.
  2. Prüfen Sie exp. Vergleichen Sie den Sekunden-Zeitstempel mit der aktuellen Zeit. Ablauf ist die häufigste Ursache von 401ern — besonders bei einer verstellten Client-Uhr oder einer aggressiv kurzen serverseitigen Lebensdauer.
  3. Prüfen Sie alg im Header. Erwartet der Server RS256 und Sie halten ein HS256-Token, scheitert die Verifikation jedes Mal. Das beißt ständig beim Wechsel zwischen Umgebungen mit unterschiedlichen Issuer-Konfigurationen.
  4. Vermuten Sie Kodierungsprobleme. In einer URL doppelt kodierte Tokens oder Base64-/Base64URL-Verwechslung (ein - als Minuszeichen fehlgelesen) können das Signatursegment verstümmeln. Der Base64-Encoder/Decoder lässt Sie ein Segment manuell dekodieren, um zu prüfen, ob der Inhalt unversehrt überlebt hat.
  5. Inhalt sieht gut aus, Verifikation scheitert trotzdem? Prüfen Sie, dass das Geheimnis oder der öffentliche Schlüssel tatsächlich zum Aussteller passt — eine falsch geladene Umgebungsvariable ist der übliche Übeltäter.

Wiederholenswert: „Dekodieren“ in den obigen Schritten prüft nur den Inhalt und braucht keinen Schlüssel. Echte Signaturverifikation muss auf einem Backend geschehen, dem Sie vertrauen, mit dem korrekten Schlüssel.

Zum Schluss

JWT setzte sich durch, weil es ein Vertrauensproblem in reine Kryptografie verwandelt: Signatur verifizieren, Inhalt vertrauen. Behalten Sie vier Dinge im Kopf — alle drei Segmente sind Base64URL-kodierter Klartext; die Signatur garantiert Integrität, nicht Geheimhaltung; HS256 teilt einen Schlüssel, während RS256 private und öffentliche Schlüssel trennt; und die Verifikation muss den Algorithmus festnageln und exp prüfen. Verinnerlichen Sie das, und Sie umgehen neunzig Prozent des Ärgers, den JWTs verursachen.