JWT
2 Tools
Grundlagen der Web-Sicherheit
Web-Sicherheit ist die Praxis, Webanwendungen und APIs vor unbefugtem Zugriff, Datenverletzungen und Angriffen zu schützen. Moderne Anwendungen verwenden Authentifizierung, Autorisierung und Kryptographie. Dabei bilden standardisierte Token-Formate wie JWT die Brücke zwischen dezentralen Diensten, ohne dass für jede Anfrage eine zentrale Sitzungsdatenbank abgefragt werden muss.
JSON Web Tokens (JWT) sind der dominante zustandslose Authentifizierungsmechanismus in der modernen Webentwicklung. Das Verständnis ihrer Struktur, Signaturalgorithmen und Schwachstellen ist grundlegend für den Aufbau sicherer APIs und Anwendungen. In Microservices-Umgebungen ermöglichen JWTs es jedem Dienst, Identität und Berechtigungen eigenständig zu prüfen, ohne Anfragen an einen zentralen Auth-Server weiterleiten zu müssen.
JSON Web Tokens (JWT)
Ein JWT ist eine kompakte, URL-sichere Methode, Ansprüche zwischen zwei Parteien darzustellen. Er besteht aus drei Base64url-kodierten Teilen, getrennt durch Punkte. Da die Signatur den gesamten Token abdeckt, kann die Gültigkeit eines JWT ohne Datenbankabfrage geprüft werden — der Empfänger benötigt lediglich den öffentlichen Schlüssel oder das gemeinsame Geheimnis.
Die drei Teile eines JWT
Enthält Metadaten über den Token: den Signaturalgorithmus (alg) und den Token-Typ (typ). Die Algorithmuswahl im Header beeinflusst die gesamte Sicherheit des Tokens — ein schwacher oder fehlender Algorithmus macht die Signatur wertlos.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9{
"alg": "HS256",
"typ": "JWT"
}Enthält die Claims: Aussagen über den Benutzer und zusätzliche Metadaten. Die Payload-Daten sind NICHT verschlüsselt, nur signiert. Das bedeutet, dass jeder, der den Token abfängt, die Payload lesen kann — sensible Daten wie Passwörter dürfen daher niemals in der Payload gespeichert werden.
eyJzdWIiOiJ1c2VyXzEyMyIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcxNzIwMDAwMH0{
"sub": "user_123",
"role": "admin",
"exp": 1717200000
}Eine kryptographische Signatur über den kodierten Header und Payload. Die Überprüfung dieser Signatur stellt sicher, dass der Token nicht manipuliert wurde. Der geheime Schlüssel (bei HMAC) bzw. der private Schlüssel (bei RSA/ECDSA) ist niemals im Token selbst enthalten und muss serverseitig sicher aufbewahrt werden.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cHMACSHA256( base64url(header) + "." + base64url(payload), secret )
Standard-JWT-Claims
Die JWT-Spezifikation definiert Standard-Claim-Namen für die Interoperabilität. Neben diesen registrierten Claims können Anwendungen eigene private Claims definieren — etwa Rollen, Berechtigungen oder Mandanten-IDs. Private Claims sollten durch ein Namespace-Präfix (z.B. die eigene Domain) eindeutig gemacht werden, um Konflikte mit zukünftigen Standards zu vermeiden:
| Claim | Name | Beschreibung |
|---|---|---|
| iss | Issuer | Identifiziert den Principal, der den Token ausgestellt hat |
| sub | Subject | Identifiziert den Principal, der das Subjekt des Tokens ist (z.B. Benutzer-ID) |
| aud | Audience | Identifiziert die Empfänger, für die der Token bestimmt ist |
| exp | Expiration | Unix-Timestamp, nach dem der Token nicht mehr akzeptiert werden darf |
| nbf | Not Before | Unix-Timestamp, vor dem der Token nicht akzeptiert werden darf |
| iat | Issued At | Unix-Timestamp, zu dem der Token ausgestellt wurde |
| jti | JWT ID | Eindeutiger Bezeichner für den Token, verhindert Token-Replay-Angriffe |
Signaturalgorithmen
Der Signaturalgorithmus wird im JWT-Header deklariert. Die richtige Wahl ist für die Sicherheit entscheidend. Es ist wichtig, den erwarteten Algorithmus im Verifier explizit festzulegen und nie auf den im Token angegebenen Wert zu vertrauen, ohne ihn vorab zu prüfen:
HS256 / HS384 / HS512Symmetrisch (HMAC)Verwendet einen gemeinsamen geheimen Schlüssel zum Signieren und Verifizieren. Einfach zu implementieren, aber der Schlüssel muss sicher an alle verifizierenden Parteien übertragen und dort geschützt gespeichert werden.
RS256 / RS384 / RS512Asymmetrisch (RSA)Verwendet einen privaten Schlüssel zum Signieren und einen öffentlichen Schlüssel zum Verifizieren. Der private Schlüssel verbleibt ausschließlich auf dem Auth-Server, während der öffentliche Schlüssel bedenkenlos an alle Verifier weitergegeben werden kann — beispielsweise über einen JWKS-Endpunkt.
ES256 / ES384 / ES512Asymmetrisch (ECDSA)Wie RSA, aber mit kleineren Schlüsseln und schnellerer Signierung. Ein ECDSA-Schlüsselpaar mit 256 Bit bietet eine vergleichbare Sicherheit wie ein 3072-Bit-RSA-Schlüssel und ist damit besonders effizient auf Geräten mit begrenzten Ressourcen.
"alg": "none"Unsigniert — GEFÄHRLICHKeine Signatur. Ein Token mit alg:none hat keine Integritätsgarantie und kann von jedem gefälscht werden.
Authentifizierungsabläufe
- 1.Benutzer sendet Benutzername und Passwort an den Login-Endpunkt
- 2.Server validiert Anmeldedaten gegen die Benutzerdatenbank
- 3.Server signiert einen JWT mit Benutzer-Claims und Ablaufzeit
- 4.Client speichert JWT (localStorage, Cookie oder Speicher)
- 5.Client sendet JWT im Authorization: Bearer-Header für nachfolgende Anfragen
- 1.Client leitet Benutzer zum Autorisierungsserver mit Code-Challenge weiter
- 2.Benutzer authentifiziert sich und autorisiert die Client-Anwendung
- 3.Auth-Server leitet zurück mit einem einmaligen Autorisierungscode
- 4.Client tauscht Code + Verifier gegen Zugriffs- und Refresh-Token aus
- 5.Client verwendet Zugriffstoken für API-Aufrufe; Refresh-Token zur Erneuerung
Häufige JWT-Schwachstellen
JWTs sind sicher, wenn sie korrekt implementiert werden. Dies sind die häufigsten Implementierungsfehler, die zu Sicherheitslücken führen. Viele dieser Schwachstellen entstehen nicht durch Fehler in der JWT-Spezifikation selbst, sondern durch fehlerhafte Bibliotheksimplementierungen oder mangelnde Validierung auf Anwendungsebene:
Einige Bibliotheken akzeptieren Tokens mit alg:none. Ein Angreifer kann die Payload ändern und alg auf none setzen, um beliebige JWTs zu fälschen. Den erlaubten Algorithmus immer explizit im Verifier festlegen — nie den Wert aus dem Token-Header ungeprüft übernehmen.
Wenn eine Bibliothek RS256 verifizieren soll, aber HS256 akzeptiert, kann ein Angreifer einen Token mit dem öffentlichen Schlüssel als HMAC-Geheimnis signieren. Den erwarteten Algorithmus immer explizit pinnen — niemals dynamisch aus dem Token-Header lesen.
Ein JWT ohne exp-Claim oder Code, der exp nicht prüft, ermöglicht die unbegrenzte Verwendung von Tokens. Abgelaufene Tokens können auch nach dem Abmelden oder Sperren eines Kontos weiterhin gültig sein, was ein erhebliches Sicherheitsrisiko darstellt.
JWT-Payloads sind Base64-kodiert, nicht verschlüsselt. Niemals Passwörter oder andere Geheimnisse in JWT-Claims speichern. Wer einen Token abfängt — etwa durch einen Man-in-the-Middle-Angriff oder XSS — kann die gesamte Payload im Klartext lesen.
HMAC-signierte JWTs mit kurzen oder vorhersehbaren Geheimnissen können offline per Brute-Force geknackt werden. Kryptographisch zufällige Geheimnisse mit mindestens 256 Bit verwenden — kurze oder sprechende Passwörter sind absolut ungeeignet.
JWTs ohne Signaturprüfung zu akzeptieren vertraut der Payload vollständig. Dies ist ein kritischer Fehler, der es jedem Benutzer ermöglicht, beliebige Claims zu erfinden. Die Signatur immer vor dem Vertrauen in Claims verifizieren.
Häufig gestellte Fragen
Standard-JWTs (JWS — JSON Web Signature) sind signiert, aber NICHT verschlüsselt. Die Payload ist Base64url-kodiert, was trivial umkehrbar ist. Wer einen JWT abfängt, kann seinen Inhalt sofort lesen. JWE (JSON Web Encryption) bietet echte Verschlüsselung, ist jedoch deutlich seltener verbreitet und erfordert zusätzliche Schlüsselverwaltung.
Zugriffstoken sollten kurzlebig sein: 5–60 Minuten ist typisch. Langlebige Tokens sind gefährlich, weil sie ohne eine Token-Sperrliste nicht widerrufen werden können. Refresh-Token (länger gültig, sicher gespeichert) für den Erhalt neuer Zugriffstoken verwenden. Je kürzer die Zugriffstoken-Lebensdauer, desto geringer ist das Schadenspotenzial eines gestohlenen Tokens.
HttpOnly-Cookies sind die sicherste Option — sie sind für JavaScript nicht zugänglich und verhindern XSS-Diebstahl. localStorage ist anfällig für XSS-Angriffe, vermeidet aber CSRF. Memory (JavaScript-Variable) ist am sichersten, überlebt jedoch keinen Seitenneuladen. Für die meisten Anwendungen bieten HttpOnly-Cookies mit SameSite=Strict den besten Kompromiss aus Sicherheit und Benutzerfreundlichkeit.
Nicht ohne serverseitigen Zustand. Die zustandslose Natur von JWTs bedeutet, dass der Server sie nicht ungültig machen kann. Lösungen: kurze Ablaufzeiten, eine Token-Sperrliste (Redis), rotierende Refresh-Token oder der Wechsel zu opaken Session-Tokens für sicherheitskritische Vorgänge. Ein hybrides Modell mit kurzen Zugriffstoken und einer Sperrliste für Refresh-Token ist in der Praxis weit verbreitet.
Session-Cookies speichern eine zufällige Session-ID; der Server sucht die Session-Daten in einer Datenbank. JWTs sind eigenständig — der Server validiert die Signatur ohne Datenbankabfrage. JWTs skalieren besser auf mehrere Server, können aber ohne zusätzliche Infrastruktur nicht widerrufen werden. Session-Cookies eignen sich besser für Anwendungen, bei denen sofortiger Widerruf (z.B. nach einem Passwort-Reset) unbedingt erforderlich ist.
Das Minimum: sub (Benutzer-ID), exp (Ablauf) und iat (ausgestellt am). iss (Aussteller) für Multi-Service-Setups hinzufügen. Payloads klein halten — JWTs werden bei jeder Anfrage übertragen. Keine sensiblen Daten oder große Profilobjekte einschließen. Rollen und Berechtigungen können aufgenommen werden, sollten aber granular und auf das Notwendige beschränkt bleiben.
RS256 (asymmetrisch) ist für die meisten Produktionssysteme besser, da nur der Auth-Server den privaten Schlüssel benötigt. Mehrere Dienste können Tokens mit dem öffentlichen Schlüssel verifizieren, ohne ein gemeinsames Geheimnis zu teilen. HS256 ist einfacher, erfordert aber, dass alle Verifier das gemeinsame Geheimnis kennen — bei Microservices ein erhebliches Risiko, da ein kompromittierter Dienst das Geheimnis preisgeben kann.
PKCE ist eine Erweiterung des OAuth2-Autorisierungscode-Flows, die Autorisierungscode-Abfangangriffe verhindert. Es ist für öffentliche Clients (SPAs, mobile Apps) erforderlich, die ein Client-Geheimnis nicht sicher speichern können.