Ein JSON Web Token ist ein kompaktes, URL-sicheres Token mit signierten JSON-Claims, mit dem Server Anfragen ohne gespeicherte Sessions prüfen. So beschreibt es auch RFC 7519 selbst – als kompaktes, URL-sicheres Mittel, Claims zwischen zwei Parteien zu übertragen –, und die beiden Gedanken darin tragen alles Weitere: Das Token enthält seine Fakten, und eine Signatur macht diese Fakten für jeden prüfbar, der den richtigen Schlüssel hat, ohne dass eine Datenbank beteiligt ist.
Das Wichtigste in Kürze
| Frage | Antwort |
|---|---|
| Die Form | header.payload.signature – drei Base64Url-Teile, durch Punkte verbunden |
| Der Kniff | Jeder kann es decodieren; nur Schlüsselinhaber können es fälschen |
| Keine Verschlüsselung | Der Payload ist lesbar – signiert ≠ geheim (dafür gibt es JWE) |
| Der Trade-off | Zustandslose Prüfung ↔ kein eingebauter Widerruf bis exp |
| Die Disziplin | Algorithmen festlegen · iss/aud/exp validieren · kurze Lebensdauer + Refresh-Rotation |
Ein JWT, decodiert
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 . eyJzdWIiOiJ1c3ItOGZrMiIsInJvbGUi… . dBjftJeZ4CVP…
header { "alg": "HS256", "typ": "JWT" }
payload { "sub": "usr-8fk2", "role": "editor",
"iss": "https://api.example.com", "aud": "example-web",
"iat": 1767024900, "exp": 1767025800 } ← 15 Minuten Lebensdauer
signature HMACSHA256( base64url(header) + "." + base64url(payload), secret )
Jeder kann die ersten beiden Teile DECODIEREN – Base64Url ist Verpackung, keine Verschlüsselung.
Nur Schlüsselinhaber können den dritten FÄLSCHEN – und genau darin liegt der ganze Kniff.
Der Kontrast, den es sich im Code anzusehen lohnt – die zustandsbehaftete Alternative, an der sich jede JWT-Entscheidung messen lassen muss:
// JavaScript / Node.js — Back4app JS SDK
// The stateful contrast: Back4app issues revocable session tokens
const user = await Parse.User.logIn('ada', 'correct-horse-battery');
const token = user.getSessionToken(); // r:abc123… — opaque, server-side state
// Every request presents it; the server can revoke it instantly:
await Parse.User.logOut(); // token invalid NOW — no waiting for an exp claim // Flutter / Dart — Back4app Flutter SDK
// The stateful contrast: Back4app issues revocable session tokens
final user = ParseUser('ada', 'correct-horse-battery', null);
await user.login();
final token = user.sessionToken; // r:abc123… — opaque, server-side state
// Every request presents it; the server can revoke it instantly:
await user.logout(); // token invalid NOW — no waiting for an exp claim // iOS / Swift — Back4app Swift SDK
// The stateful contrast: Back4app issues revocable session tokens
let user = try await User.login(username: "ada", password: "correct-horse-battery")
let token = user.sessionToken // r:abc123… — opaque, server-side state
// Every request presents it; the server can revoke it instantly:
try await User.logout() // token invalid NOW — no waiting for an exp claim // Android / Kotlin — Back4app Android SDK
// The stateful contrast: Back4app issues revocable session tokens
val user = ParseUser.logIn("ada", "correct-horse-battery")
val token = user.sessionToken // r:abc123… — opaque, server-side state
// Every request presents it; the server can revoke it instantly:
ParseUser.logOut() // token invalid NOW — no waiting for an exp claim Wie die Prüfung funktioniert
Die Präzision, die viele Erklärungen auslassen: “JWT” bezeichnet das Claims-Format; was tatsächlich alle herumreichen, ist ein JWS (RFC 7515) – die signierte Serialisierung –, während JWE das verschlüsselte Geschwister für Payloads ist, die unlesbar bleiben müssen. Und die Prüfung besteht aus zwei Aufgaben, nicht aus einer: erst die Signatur prüfen, dann die Claims validieren – exp und nbf gegen die Uhr, iss gegen Ihre Allowlist vertrauenswürdiger Aussteller, aud gegen die Kennung dieses Dienstes. Ein einwandfrei signiertes Token, das abgelaufen ist, vom falschen Aussteller stammt oder für eine andere Zielgruppe ausgestellt wurde, ist ein einwandfrei signierter Angriff.
Claims: das Vokabular des Payloads
| Claim | Name | Aufgabe des Prüfers |
|---|---|---|
iss | Issuer (Aussteller) | Ist das ein Aussteller, dem ich vertraue? |
sub | Subject (Subjekt) | Um wen geht es – die stabile Nutzer-ID |
aud | Audience (Zielgruppe) | Wurde es für mich ausgestellt? Fremde Tokens ablehnen |
exp | Expiration (Ablaufzeit) | Nach diesem Unix-Zeitstempel ablehnen |
iat / nbf | Issued at / Not before | Das Gültigkeitsfenster auf Plausibilität prüfen |
jti | Token-ID | Eindeutiger Bezeichner – der Anker, den eine Denylist braucht |
| eigene | Rollen, Tenant, Tarif … | App-Semantik – minimal halten, nie geheim |
Halten Sie Payloads aus zwei Gründen schlank: Tokens reisen bei jeder Anfrage als Header mit (Cookies sind auf etwa 4 KB begrenzt, und jeder Claim ist wiederholte Bandbreite), und alles darin ist für jeden lesbar, der das Token besitzt.
JWT vs. Session-Tokens
| JWT (zustandslos) | Session-Token (zustandsbehaftet) | |
|---|---|---|
| Das Token ist | Der Zustand selbst, signiert | Ein undurchsichtiger Zeiger auf Serverzustand |
| Kosten pro Anfrage | Signaturprüfung, kein Lookup | Ein Lookup im Session-Speicher |
| Widerruf | Keiner bis exp – so gewollt | Sofort – Session löschen |
| Dienstübergreifende Authentifizierung | Jeder Dienst mit dem Schlüssel prüft | Dienste müssen den Session-Speicher teilen |
| Abmeldung bedeutet | Client verwirft; Token bleibt gültig | Token ist tatsächlich tot |
| Ideal für | APIs, Microservices, Prüfung durch Dritte | Apps mit einem Backend, sensible Sessions |
Die unmoderne Wahrheit, mit der inzwischen mehrere Best-Practice-Leitfäden beginnen: Für eine serverseitig gerenderte App mit einem einzigen Backend sind Framework-Sessions einfacher und besser kontrollierbar – JWTs lohnen sich, wenn Tokens über Dienste hinweg geprüft werden müssen oder von Parteien, die nicht bei jeder Anfrage beim Aussteller nachfragen sollen.
Das Widerrufsproblem, ehrlich betrachtet
Zustandslosigkeit ist die Unfähigkeit zu widerrufen – dieselbe Eigenschaft, zweimal beschrieben. Ein signiertes Token ist bis exp gültig, egal was seitdem passiert ist: Abmeldung, Passwortänderung, Kontosperre. Jede Lösung führt wieder Zustand ein, also wählen Sie die Variante: eine Denylist über jti + iss (die von OWASP empfohlene Konstruktion), bei jeder Anfrage geprüft – wenig Zustand, aber Zustand; Schlüsselversionierung, die alle auf einmal widerruft; oder die Standardarchitektur – kurzlebige Access Tokens (5–15 Minuten) plus widerrufbare Refresh Tokens mit Rotation: Jede Erneuerung stellt ein neues Refresh Token aus und zieht das alte zurück, sodass ein gestohlenes beim ersten erneuten Einsatz stirbt, und die Wiederverwendung eines zurückgezogenen Tokens meldet den Diebstahl und entwertet die gesamte Token-Familie. Die Widerrufslatenz entspricht dann der Lebensdauer des Access Tokens – der eigentliche Grund, warum diese Lebensdauern kurz sind.
Einen Algorithmus wählen – und die Angriffe auf diese Wahl
| HS256 (HMAC) | RS256 (RSA) | Ed25519 / ES256 | |
|---|---|---|---|
| Schlüssel | Ein gemeinsames Geheimnis | Privat signiert, öffentlich prüft | Privat signiert, öffentlich prüft |
| Prüfer brauchen | Das Geheimnis (können damit auch fälschen!) | Nur den öffentlichen Schlüssel | Nur den öffentlichen Schlüssel |
| Passt für | Aussteller = Prüfer, eine Partei | Mehrere Dienste, Dritte | Dasselbe, kleinere/schnellere Signaturen |
| Scharfe Kante | Kurze Geheimnisse lassen sich aus einem abgefangenen Token offline per Brute Force knacken – ≥256 zufällige Bits verwenden | Größere Tokens, langsamer | Jüngere Bibliotheksunterstützung |
Der Angriffsteil, für den es RFC 8725 gibt, in drei Sätzen. alg: "none" ist ein zulässiger Header-Wert – Bibliotheken, die ihn respektieren, akzeptieren unsignierte Tokens. Der Confusion-Angriff: Einem Prüfer, der den Header des Tokens den Algorithmus wählen lässt, kann man ein “HS256”-Token unterschieben, das mit dem öffentlichen RSA-Schlüssel des Servers als HMAC-Geheimnis signiert wurde – ein öffentlicher Wert, als privater benutzt. Beide Angriffe scheitern an derselben Maßnahme: Der Prüfer legt die akzeptierten Algorithmen und Schlüssel in der Konfiguration fest und überlässt die Wahl nie dem Header.
Wo JWTs im Browser gespeichert werden
| Speicherort | Stiehlt XSS es? | Sendet CSRF es mit? | Übersteht Neuladen? | Urteil |
|---|---|---|---|---|
| localStorage | Ja | Nein | Ja | Vermeiden – per Skript lesbar |
| Einfaches Cookie | Ja (per Skript lesbar) | Ja | Ja | Das Schlechteste beider Welten |
| HttpOnly- + Secure- + SameSite-Cookie | Nein | Durch SameSite abgeschwächt | Ja | Gut – für das Refresh Token |
| Im Arbeitsspeicher | Nur während der Injektion | Nein | Nein | Gut – für das Access Token |
| Backend-for-Frontend hält die Tokens | Browser hat sie nie | Cookie-Regeln gelten | Ja | Am stärksten für SPAs |
Das Bedrohungsmodell, nicht die Folklore: localStorage tauscht CSRF-Immunität gegen XSS-Diebstahl, Cookies tauschen umgekehrt – deshalb teilt der Konsens das Paar auf: Access Token im Arbeitsspeicher, Refresh Token in einem gehärteten Cookie.
Typische Anwendungsfälle
- API-Authentifizierung – das Bearer Token hinter
Authorization-Headern bei REST- und GraphQL-APIs. - Identität zwischen Microservices – ein vom Gateway ausgestelltes Token, das jeder Dienst unabhängig prüft, ohne gemeinsamen Session-Speicher.
- ID Tokens von OpenID Connect – die signierte Identitätszusicherung hinter jedem Social Login – immer ein JWT.
- Übergaben zwischen Systemen – signierte Links, Webhook-Payloads, Download-Freigaben: Claims, die eine Partei prüft, die bei Ihnen nicht zurückfragen kann.
- Zustandslose Autorisierungshinweise – Rollen und Tenant-IDs in Claims, wobei die maßgebliche Prüfung weiterhin serverseitig stattfindet.
Sollten Sie JWTs oder Sessions verwenden? Eine Entscheidungsmatrix
| Ihre Situation | Greifen Sie zu |
|---|---|
| Ein Backend, serverseitig gerenderte App | Sessions – einfacher, sofort widerrufbar |
| Öffentliche API, von vielen Diensten genutzt | JWTs, asymmetrische Schlüssel |
| Microservices hinter einem Gateway | JWTs – lokal prüfen, kein gemeinsamer Speicher |
| Sofortige Sperrung ist Pflicht | Sessions oder JWTs + Denylist und kurzes exp |
| Dritte müssen Ihre Zusicherungen prüfen | JWTs – das ist das Heimspiel des Formats |
| Mobile App gegen ein BaaS | Der Session-Mechanismus der Plattform – die Wahl ist schon getroffen |
Grenzen und Trade-offs
- Unwiderrufbarkeit ist strukturell. Jede Abhilfe – Denylists, kurze Lebensdauern, Rotation – holt einen Teil des Zustands zurück, den Sie entfernt haben; kalkulieren Sie das ein, bevor Sie sich für Zustandslosigkeit entscheiden.
- Claims veralten. Rollen sind eine Momentaufnahme bei der Ausstellung; ein herabgestufter Admin bleibt bis zum Ablauf Admin. Kurze Lebensdauern begrenzen dieses Fenster.
- Der Payload ist öffentlich. Behandeln Sie ihn als lesbar für den Nutzer und jeden Token-Dieb – Kennungen ja, Geheimnisse und personenbezogene Daten nein.
- Bibliotheks-Standardwerte haben schon Schaden angerichtet. Festgelegte Algorithmen, Claim-Validierung und
typ-Prüfung liegen in Ihrer Konfigurationsverantwortung, nicht in den Garantien der Bibliothek. - Größe summiert sich. Jeder Claim reist bei jeder Anfrage mit; großzügige Payloads belasten mobile Bandbreite und können Cookie-Grenzen sprengen.
Tokens mit Back4app
Back4app ist eine Open-Source-Plattform für Backend as a Service (BaaS), die eine verwaltete Datenbank, automatisch generierte REST- und GraphQL-APIs, Authentifizierung, Dateispeicher und Serverless-Funktionen mit Cloud Code kombiniert. Die Wahl der Plattform selbst illustriert die Entscheidungsmatrix: Client-Sessions nutzen widerrufbare, serverseitige Session-Tokens – die Code-Tabs oben –, sodass Abmeldung, Passwortänderungen und das Beenden von Sessions im Dashboard sofort wirken, ohne dass ein Ablauffenster abgewartet werden muss. JWTs erscheinen dort, wo sie hingehören: Die OIDC-ID-Tokens von Identity Providern werden beim Social Login serverseitig von Auth-Adaptern geprüft, und Cloud-Code-Funktionen können mit Standardbibliotheken JWTs für Übergaben an Dritte ausstellen oder prüfen – mit dem Signaturgeheimnis in der serverseitigen Konfiguration, niemals an Clients ausgeliefert. Zustandsbehaftet, wo Kontrolle zählt, zustandslos an den Rändern, wo die Prüfung reisen muss: die Architektur, für die dieser Artikel plädiert, fertig zusammengesetzt.
Häufige Fragen
Was ist ein JWT, einfach erklärt?
Ein signierter, Base64-codierter JSON-"Ausweis", den ein Server bei der Anmeldung ausstellt. Der Client legt ihn bei jeder Anfrage vor, und der Server prüft die Signatur, statt eine Session nachzuschlagen – das Token selbst sagt, wer Sie sind und bis wann. Laut dem RFC, der es definiert, wird es wie das englische Wort "jot" ausgesprochen.
Aus welchen drei Teilen besteht ein JWT?
Header (Token-Typ und Signaturalgorithmus), Payload (die Claims – die eigentlichen JSON-Daten) und Signatur, jeweils Base64Url-codiert und mit Punkten zu header.payload.signature verbunden. Die Signatur wird über die ersten beiden Teile berechnet, sodass jede Manipulation daran die Prüfung scheitern lässt.
Ist ein JWT verschlüsselt?
Nein – codiert, nicht verschlüsselt. Base64Url ist ein Transportformat, das jeder umkehren kann; fügen Sie ein beliebiges JWT in einen Decoder ein, und der Payload ist lesbar. Die Signatur verhindert Manipulation, nicht das Mitlesen. Legen Sie niemals Geheimnisse oder sensible personenbezogene Daten in einen JWT-Payload; für echte Vertraulichkeit gibt es die verschlüsselte Variante (JWE).
Was ist der Unterschied zwischen einem JWT und einem Session-Token?
Wo der Zustand liegt. Ein Session-Token ist eine undurchsichtige ID, die auf serverseitigen Zustand zeigt – ein Lookup pro Anfrage, sofort widerrufbar. Ein JWT trägt den Zustand in sich – kein Lookup, prüfbar von jedem Dienst, der den Schlüssel hat, aber gültig bis zur Ablaufzeit, egal was passiert. Zustandslose Skalierung gegen sofortige Kontrolle.
Wo sollte ich ein JWT im Browser speichern?
Nicht im localStorage – jedes eingeschleuste Skript kann es lesen, womit jede XSS-Lücke zum Token-Diebstahl wird. Aktueller Konsens: das Access Token im Arbeitsspeicher, das Refresh Token in einem HttpOnly-, Secure- und SameSite-Cookie, und prüfen Sie das Backend-for-Frontend-Muster, das Tokens ganz aus dem Browser heraushält.
Kann ein JWT widerrufen werden?
Nicht von Haus aus – ein signiertes Token ist bis zu seinem exp-Claim gültig; das ist der Preis der Zustandslosigkeit. Alle Umgehungen führen wieder Zustand ein: eine Denylist über den jti-Claim, versionierte Schlüssel oder – die Standardantwort – sehr kurze Lebensdauern für Access Tokens, kombiniert mit widerrufbaren, rotierenden Refresh Tokens.
Was ist der Unterschied zwischen HS256 und RS256?
Symmetrie. HS256 signiert und prüft mit einem einzigen gemeinsamen Geheimnis – nur dann in Ordnung, wenn Aussteller und Prüfer dieselbe Partei sind, und nur mit einem langen, zufälligen Geheimnis. RS256 (und das neuere Ed25519) signiert mit einem privaten Schlüssel, während jeder mit dem öffentlichen prüft – der Standard, sobald mehr als ein Dienst Tokens prüft.
Was ist der Unterschied zwischen JWT und OAuth?
Verschiedene Kategorien: JWT ist ein Token-Format, OAuth 2.0 ein Autorisierungs-Framework. Beide lassen sich kombinieren – OAuth-Abläufe stellen häufig Access Tokens aus, die zufällig JWTs sind, und ID Tokens von OpenID Connect sind es immer. Das eine sagt, wie ein Token aufgebaut ist; das andere, wie Tokens ausgegeben werden.