Zum Hauptinhalt springen

← Zurück zum Blog

Was ist ein JWT? Wie JSON Web Tokens funktionieren (und wie man eines liest)

Wer ein Login-System gebaut oder debuggt hat, ist dem JWT begegnet — einem kompakten Token, das zwischen Client und Server wandert, um zu beweisen, wer jemand ist. So funktioniert es und so liest man eines sicher.

Dekodiere selbst eines, ohne Schlüssel. Fügt man das Standard-Beispiel-Token aus der JWT-Doku in unseren JWT-Decoder ein, kommen die zwei lesbaren Hälften zurück — Header { "alg": "HS256", "typ": "JWT" } und Payload { "sub": "1234567890", "name": "John Doe", "iat": 1516239022 } — ohne jedes Geheimnis. Das ist das Wichtigste an JWTs: Die Claims reisen im Klartext. Die Signatur belegt, dass das Token von jemandem mit dem Schlüssel ausgestellt und seither nicht verändert wurde — eine völlig andere Garantie als Vertraulichkeit. Unser Decoder läuft im Browser, du kannst ein echtes Token also gefahrlos prüfen.

Die drei Teile

Ein JWT sind drei durch Punkte verbundene Base64URL-Strings: header.payload.signature.

  • Header — Metadaten, vor allem der Signaturalgorithmus, z. B. {"alg":"HS256","typ":"JWT"}.
  • Payload — die Claims, ein JSON-Objekt mit Daten über den Nutzer und den Token.
  • Signatur — eine kryptografische Signatur über Header und Payload, erzeugt mit einem Geheimnis (oder privaten Schlüssel), zur Erkennung von Manipulation.

Die ersten beiden Teile kannst du mit einem JWT-Decoder aufteilen und lesen.

Gängige Claims

Die Payload enthält Claims, einige standardisiert:

  • sub — Subjekt (meist die Nutzer-ID).
  • iss — Aussteller (wer den Token erstellt hat).
  • iat — Ausstellungszeit (ein Unix-Timestamp).
  • exp — Ablaufzeit (ein Unix-Timestamp). Danach sollte der Token abgelehnt werden.
  • aud — vorgesehene Zielgruppe.

Plus beliebige eigene Claims deiner App (Rollen, E-Mail usw.).

Wie JWTs zur Authentifizierung dienen

Typischer zustandsloser Ablauf: Du meldest dich an, der Server gibt ein signiertes JWT zurück, und dein Client sendet es bei jeder Anfrage mit (meist im Authorization: Bearer …-Header). Der Server verifiziert die Signatur und prüft exp — ist es gültig, vertraut er den Claims ohne Datenbankabfrage. Diese Zustandslosigkeit ist der Hauptvorteil.

Signiert, (meist) nicht verschlüsselt

Die meisten JWTs sind signiert (JWS), nicht verschlüsselt. Signieren beweist Integrität und Echtheit, aber die Payload ist nur Base64URL-kodiert — jeder kann sie lesen. Also:

  • Lege nie Geheimnisse in die Payload (Passwörter, API-Schlüssel, private Daten).
  • Verschlüsselung ist etwas anderes (JWE) und viel seltener.

Hier löst sich die meiste JWT-Verwirrung, und sie löst sich als Ausgabe. Wir haben das Token aus der JWT-Spezifikation in unseren JWT-Decoder eingefügt und keinerlei Schlüssel angegeben. Zurück kam der Header

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

und die Payload

{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}

Es wurde nichts entschlüsselt, weil nichts verschlüsselt war. Die beiden Segmente sind Base64url-Text, und die Signatur schützt sie vor Veränderung, nicht vor Lesen. Wer das Token hat, liest jeden Claim darin — deshalb darf ein JWT nie etwas tragen, das man nicht in eine URL schreiben würde.

Sicherheitsregeln, die zählen

  • Verifiziere die Signatur immer serverseitig mit deinem geheimen/öffentlichen Schlüssel. Dekodieren (wie unser Tool) ist keine Verifizierung.
  • Prüfe exp. Ein abgelaufener Token muss abgelehnt werden.
  • HS256 vs. RS256: HS256 nutzt ein gemeinsames Geheimnis; RS256 signiert mit einem privaten und verifiziert mit einem öffentlichen Schlüssel — besser, wenn mehrere Dienste verifizieren, aber nicht ausstellen.
  • Füge nie einen echten Schlüssel in ein Online-Tool ein. Einen Token zum Prüfen der Claims zu dekodieren ist in Ordnung; das Verifizieren braucht den Schlüssel und gehört in deinen eigenen Code.

Einen Token lesen

Zum Debuggen eines Auth-Problems — ist der Token abgelaufen? hat er die richtige Rolle? — dekodiere ihn und prüfe die Payload. Der kostenlose JWT-Decoder zeigt Header und Payload und wandelt exp in eine lesbare Zeit um, alles lokal im Browser, sodass der Token nie hochgeladen wird.

Damit ist auch die praktische Frage geklärt, was man loggen darf. { "sub": "1234567890", "name": "John Doe", "iat": 1516239022 } ist unbedenklich — es ist für jeden, der das Token hat, ohnehin lesbar. Das dritte Segment ist es nicht: Es ist der einzige Teil, der beweist, dass die ersten zwei nicht bearbeitet wurden, und ein vollständiges Token in einen Fehlerbericht zu kleben übergibt bis zum Ablauf ein funktionierendes Zugangsmittel.

Ein dekodiertes Beispiel

Nimm diesen weit verbreiteten Beispiel-Token:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Dekodiert man die ersten beiden Teile, ergibt sich:

// Header
{ "alg": "HS256", "typ": "JWT" }
// Payload
{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }

Der dritte Teil ist die Signatur — sie lässt sich nicht „lesen”; sie beweist nur, dass die ersten beiden unverändert sind.

HS256 vs. RS256 im Überblick

HS256RS256
FamilieHMAC-SHA256 (symmetrisch)RSA-SHA256 (asymmetrisch)
Schlüsselein gemeinsames Geheimnisprivater Schlüssel signiert, öffentlicher verifiziert
Wer einen gültigen Token erzeugen kannjeder mit dem Geheimnisnur der Inhaber des privaten Schlüssels
Am besten, wennein Dienst ausstellt und verifiziertviele verifizieren, einer stellt aus

Umgang mit exp und iat

exp und iat sind Unix-Timestamps — Sekunden seit dem 1.1.1970 UTC, keine Millisekunden. Das 1516239022 oben ist der 18.01.2018. Wandle sie mit dem Timestamp-Konverter um oder lies den Unix-Timestamp-Leitfaden, falls die Zahlen fremd wirken.

Zwei weitere Sicherheitsfallen

  • Lehne alg: none ab und lege den erwarteten Algorithmus fest — sonst kann ein Angreifer die Signatur entfernen oder RS256 zu HS256 herabstufen.
  • JWTs sind vor exp schwer zu widerrufen. Halte Laufzeiten kurz und nutze für Sensibles Refresh-Tokens.

Denk daran: Unser Decoder dekodiert nur — er verifiziert nie. Behandle eine dekodierte, aber unverifizierte Payload als nicht vertrauenswürdig, bis dein Server die Signatur prüft.