JWT-Struktur erklärt: Header, Payload und Signatur
In der modernen Ära der Webentwicklung ist die Sicherung der Kommunikation zwischen Clients und Servern von entscheidender Bedeutung. JSON Web Tokens (JWT) haben sich als Industriestandard für die sichere Übertragung von Claims (Ansprüchen) zwischen zwei Parteien etabliert. Unabhängig davon, ob Sie eine Single-Page-Anwendung (SPA), eine mobile App oder eine Microservices-Architektur erstellen, ist das Verständnis der Funktionsweise von JWTs unerlässlich für die Implementierung einer robusten Authentifizierung und Autorisierung.
Obwohl viele Entwickler Bibliotheken für den Umgang mit JWTs verwenden, ermöglicht ein tiefes Verständnis ihrer internen Struktur ein besseres Debugging, Sicherheitsaudits und fundierte architektonische Entscheidungen. In diesem umfassenden Leitfaden werden wir die drei Teile eines JWT analysieren, den Authentifizierungsfluss erläutern und Best Practices für die Sicherheit besprechen.
Was ist ein JSON Web Token (JWT)?
Ein JSON Web Token (JWT) ist ein offener Standard (RFC 7519), der eine kompakte und eigenständige Methode zur sicheren Übertragung von Informationen zwischen Parteien als JSON-Objekt definiert. Diese Informationen können verifiziert werden und sind vertrauenswürdig, da sie digital signiert sind. JWTs können mit einem Geheimnis (mit dem HMAC-Algorithmus) oder einem öffentlichen/privaten Schlüsselpaar unter Verwendung von RSA oder ECDSA signiert werden.
Die „eigenständige“ Natur von JWTs ist ihr größter Vorteil. Sie enthalten alle notwendigen Informationen über einen Benutzer, was bedeutet, dass der Server nicht bei jeder Anfrage eine Datenbank abfragen muss, um die Identität des Benutzers zu verifizieren. Dies macht JWTs ideal für verteilte Systeme und horizontale Skalierung.
Häufige Anwendungsfälle sind:
- Autorisierung: Das häufigste Szenario für die Verwendung von JWT. Sobald der Benutzer angemeldet ist, enthält jede nachfolgende Anfrage das JWT, sodass der Benutzer auf Routen, Dienste und Ressourcen zugreifen kann, die mit diesem Token zulässig sind.
- Informationsaustausch: JWTs sind eine gute Möglichkeit, Informationen sicher zwischen Parteien zu übertragen. Da JWTs signiert werden können – zum Beispiel mit öffentlichen/privaten Schlüsselpaaren –, können Sie sicher sein, dass die Absender die sind, für die sie sich ausgeben. Da die Signatur zudem aus dem Header und der Payload berechnet wird, können Sie auch verifizieren, dass der Inhalt nicht manipuliert wurde.
Die drei Teile eines JWT
In seiner kompakten Form besteht ein JSON Web Token aus drei Teilen, die durch Punkte (.) getrennt sind:
- Header
- Payload
- Signatur
Daher sieht ein JWT typischerweise wie folgt aus:
xxxxx.yyyyy.zzzzz
Lassen Sie uns jeden Teil analysieren, um zu sehen, was sie enthalten und wie sie kodiert sind. Wenn Sie jemals ein echtes Token untersuchen müssen, können Sie unseren JWT-Decoder verwenden, um genau zu sehen, was sich darin befindet.
Teil 1: Der Header
Der Header besteht typischerweise aus zwei Teilen: dem Typ des Tokens, also JWT, und dem verwendeten Signaturalgorithmus, wie HMAC SHA256 oder RSA.
{
"alg": "HS256",
"typ": "JWT"
}
Anschließend wird dieses JSON Base64Url-kodiert, um den ersten Teil des JWT zu bilden. Es ist wichtig zu beachten, dass die Base64Url-Kodierung keine Verschlüsselung ist; sie ist lediglich eine Möglichkeit, binärähnliche Daten in einem URL-freundlichen String-Format darzustellen.
Das Feld alg (Algorithmus) ist kritisch. Es teilt dem Empfänger mit, wie die Signatur zu verifizieren ist. Dieses Feld war jedoch in der Vergangenheit die Quelle vieler Sicherheitslücken (wie der „none“-Algorithmus-Angriff), weshalb moderne Bibliotheken verlangen, dass Sie die erwarteten Algorithmen während der Verifizierung explizit definieren.
Teil 2: Die Payload (Claims)
Der zweite Teil des Tokens ist die Payload, die die Claims (Ansprüche) enthält. Claims sind Aussagen über eine Entität (typischerweise den Benutzer) und zusätzliche Daten. Es gibt drei Arten von Claims: registrierte, öffentliche und private Claims.
- Registrierte Claims: Dies ist ein Satz vordefinierter Claims, die nicht obligatorisch, aber empfohlen sind, um eine Reihe nützlicher, interoperabler Claims bereitzustellen. Einige davon sind:
iss(Issuer/Aussteller),exp(Expiration Time/Ablaufzeit),sub(Subject/Betreff),aud(Audience/Zielgruppe) und andere. - Öffentliche Claims: Diese können von denjenigen, die JWTs verwenden, frei definiert werden. Um Kollisionen zu vermeiden, sollten sie jedoch im IANA JSON Web Token Registry definiert oder als URI mit einem kollisionsresistenten Namespace festgelegt werden.
- Private Claims: Dies sind benutzerdefinierte Claims, die erstellt wurden, um Informationen zwischen Parteien zu teilen, die sich auf deren Verwendung geeinigt haben, und die weder registriert noch öffentlich sind.
Eine Beispiel-Payload könnte so aussehen:
{
"sub": "1234567890",
"name": "Max Mustermann",
"admin": true,
"iat": 1516239022,
"exp": 1516242622
}
Die Payload wird dann Base64Url-kodiert, um den zweiten Teil des JSON Web Tokens zu bilden. Sie können unseren JWT-Decoder verwenden, um diese Claims schnell aus jedem Token zu extrahieren, dem Sie während der Entwicklung begegnen.
Teil 3: Die Signatur
Um den Signaturteil zu erstellen, müssen Sie den kodierten Header, die kodierte Payload, ein Geheimnis und den im Header angegebenen Algorithmus nehmen und dies signieren.
Wenn Sie beispielsweise den HMAC SHA256-Algorithmus verwenden möchten, wird die Signatur wie folgt erstellt:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
Die Signatur wird verwendet, um zu verifizieren, dass die Nachricht unterwegs nicht geändert wurde, und im Falle von Token, die mit einem privaten Schlüssel signiert wurden, kann sie auch verifizieren, dass der Absender des JWT derjenige ist, für den er sich ausgibt. Dies ist der kritischste Teil des JWT, da er die Integritätsgarantie bietet.
Wie die JWT-Authentifizierung funktioniert (Der Flow)
Der typische Ablauf für eine JWT-basierte Authentifizierung folgt diesen Schritten:
- Login-Anfrage: Der Client sendet seine Anmeldedaten (z. B. Benutzername und Passwort) an den Server.
- Token-Generierung: Der Server validiert die Anmeldedaten und erstellt, falls sie korrekt sind, ein JWT. Der Server signiert das JWT mit einem geheimen Schlüssel oder einem privaten Schlüssel.
- Token-Antwort: Der Server sendet das JWT an den Client zurück.
- Speicherung: Der Client speichert das Token, normalerweise im
localStorageoder in einemHttpOnly-Cookie. - Nachfolgende Anfragen: Bei jeder Anfrage an eine geschützte Ressource sendet der Client das JWT im
Authorization-Header unter Verwendung desBearer-Schemas:Authorization: Bearer <token>. - Verifizierung: Der Server empfängt die Anfrage, extrahiert das Token und verifiziert seine Signatur mit dem Geheimnis oder dem öffentlichen Schlüssel. Wenn die Signatur gültig ist und das Token nicht abgelaufen ist, gewährt der Server Zugriff auf die angeforderte Ressource.
Dieser Flow macht es überflüssig, dass der Server für jeden Benutzer einen Sitzungsstatus im Speicher (oder in einer Datenbank/Redis) verwalten muss, was den Overhead auf Serverseite erheblich reduziert und eine bessere Skalierbarkeit ermöglicht.
Sicherheits-Best-Practices: Warum Sie keine Geheimnisse im JWT speichern sollten
Ein weit verbreiteter Irrglaube unter Entwicklern ist, dass JWTs ein sicherer Weg sind, um sensible Daten zu verbergen. Das ist falsch. Sofern Sie nicht JSON Web Encryption (JWE) verwenden, ist die Payload eines JWT nur Base64Url-kodiert, nicht verschlüsselt.
Jeder, der das Token abfängt, kann die Payload leicht dekodieren und die darin enthaltenen Informationen lesen. Daher sollten Sie niemals Passwörter, Sozialversicherungsnummern oder andere sensible Geheimnisse in der Payload speichern. Um sicherzustellen, dass Sie starke Geheimnisse für Ihren Signaturprozess verwenden, können Sie unseren Passwort-Generator verwenden, um Schlüssel mit hoher Entropie zu erstellen.
Wichtige Sicherheitstipps:
- Immer HTTPS verwenden: Um Man-in-the-Middle-Angriffe (MITM) zu verhindern, bei denen Ihre Token gestohlen werden könnten.
- Kurz halten: Legen Sie eine kurze Ablaufzeit (
exp-Claim) fest, um das Zeitfenster für einen Angreifer zu minimieren, falls ein Token gestohlen wird. - HttpOnly-Cookies verwenden: Wenn Sie JWTs im Browser speichern, hilft die Verwendung der Flags
HttpOnlyundSecurefür Cookies dabei, sich vor Cross-Site-Scripting-Angriffen (XSS) zu schützen. - Algorithmus validieren: Vertrauen Sie nicht blind dem
alg-Header. Codieren Sie den erwarteten Algorithmus fest in Ihre Verifizierungslogik.
JWT vs. Session-Cookies: Hauptunterschiede
Die Wahl zwischen JWT und herkömmlichen Session-Cookies hängt von den Anforderungen Ihrer Anwendung ab. Hier ist ein Vergleich:
| Merkmal | Session-Cookies | JSON Web Tokens |
|---|---|---|
| Status | Zustandsbehaftet (auf dem Server gespeichert) | Zustandslos (auf dem Client gespeichert) |
| Skalierbarkeit | Schwieriger (erfordert Sticky Sessions oder Shared Store) | Einfacher (völlig unabhängig) |
| Widerruf | Einfach (vom Server löschen) | Schwierig (erfordert eine Blacklist oder kurze Ablaufzeit) |
| Größe | Klein (nur eine Session-ID) | Groß (enthält alle Claims) |
Gängige JWT-Algorithmen (HS256 vs. RS256)
Es gibt zwei primäre Arten von Signaturalgorithmen, die bei JWTs verwendet werden: symmetrische und asymmetrische.
HS256 (HMAC mit SHA-256) ist ein symmetrischer Algorithmus, was bedeutet, dass derselbe geheime Schlüssel sowohl zum Signieren als auch zum Verifizieren des Tokens verwendet wird. Er ist einfach zu implementieren, erfordert jedoch, dass sowohl der Aussteller als auch der Konsument das Geheimnis sicher teilen.
RS256 (RSA-Signatur mit SHA-256) ist ein asymmetrischer Algorithmus, was bedeutet, dass er einen privaten Schlüssel zum Signieren des Tokens und einen öffentlichen Schlüssel zum Verifizieren verwendet. Dies ist sicherer für Szenarien, in denen der Dienst, der das Token ausstellt, ein anderer ist als der Dienst, der es konsumiert (z. B. OAuth2-Anbieter wie Google oder Auth0).
| Algorithmus | Typ | Schlüsselanforderungen | Bestens geeignet für |
|---|---|---|---|
| HS256 | Symmetrisch | Ein gemeinsamer geheimer Schlüssel | Interne Apps, kleine Teams |
| RS256 | Asymmetrisch | Privater Schlüssel (Signieren), Öffentlicher Schlüssel (Verifizieren) | Microservices, öffentliche APIs, Identity Provider |
Fazit
JSON Web Tokens bieten eine leistungsstarke und flexible Möglichkeit, die Authentifizierung in modernen Webanwendungen zu handhaben. Durch das Verständnis der dreiteiligen Struktur – Header, Payload und Signatur – können Entwickler Systeme bauen, die sowohl skalierbar als auch sicher sind. Es ist jedoch wichtig zu bedenken, dass JWTs Werkzeuge für Integrität und Authentifizierung sind, nicht für Geheimhaltung.
Priorisieren Sie bei der Implementierung von JWTs immer die Sicherheit, indem Sie starke Signaturschlüssel verwenden, HTTPS erzwingen und die Payloads schlank halten. Egal, ob Sie ein Token mit unserem JWT-Decoder debuggen oder ein neues Geheimnis mit unserem Passwort-Generator generieren: Die richtigen Werkzeuge und Kenntnisse sind der erste Schritt zur Entwicklung großartiger Software.