NetLabToolsNetLabTools

JWT erklärt: Aufbau, Sicherheit und Best Practices

Was ist ein JWT, welche Algorithmen gibt es und wie nutzt man sie sicher? Inklusive der häufigsten Pitfalls.

9 Min. Lesezeit

JSON Web Tokens (JWT) sind heute der De-facto-Standard für stateless Authentifizierung in APIs. Sie sind elegant, kompakt und – falsch eingesetzt – ein hervorragendes Sicherheitsrisiko. Dieser Artikel erklärt Aufbau, Algorithmen und die wichtigsten Pitfalls.

Was ist ein JWT?

Ein JWT ist ein String mit drei Teilen, getrennt durch Punkte: Header.Payload.Signature. Jeder Teil ist Base64URL-kodiert (wie Base64, aber ohne Padding und mit URL-sicheren Zeichen).

Wichtig: JWTs sind signiert, nicht verschlüsselt. Jeder kann den Payload lesen, indem er ihn Base64-decodiert. Speichere also keine Passwörter oder andere Geheimnisse darin.

Beispiel-Token zerlegt

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNzMwMDAwMDAwLCJleHAiOjE3MzAwMDM2MDB9
.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Header (decodiert):

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

Payload (decodiert):

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1730000000,
  "exp": 1730003600
}

Die Signatur entsteht aus HMAC_SHA256(base64url(header) + "." + base64url(payload), secret). Der Server prüft beim Empfang nur diese Signatur – ist sie gültig, ist der Token nicht manipuliert.

Signatur-Algorithmen: HS256 vs RS256 vs ES256

  • HS256 (HMAC-SHA256) – Symmetrisch. Das gleiche Geheimnis signiert und verifiziert. Schnell und einfach, aber jeder, der verifizieren kann, kann auch signieren. Geeignet, wenn ein einziger Service beides macht.
  • RS256 (RSA-SHA256) – Asymmetrisch. Privater Key signiert, öffentlicher Key verifiziert. Ideal, wenn mehrere Services Tokens prüfen sollen, ohne signieren zu dürfen. Standard bei OIDC/OAuth2.
  • ES256 (ECDSA P-256) – Wie RS256, aber mit Elliptic Curves. Kürzere Signaturen (~64 Byte statt ~256), schneller zu verifizieren. Heute die empfohlene Wahl für neue Systeme.

Häufige Claims

  • iss (issuer) – wer den Token ausgestellt hat
  • sub (subject) – über wen der Token ist (User-ID)
  • aud (audience) – für wen der Token bestimmt ist
  • exp (expiration) – Unix-Timestamp, ab wann ungültig
  • iat (issued at) – wann ausgestellt
  • nbf (not before) – ab wann gültig
  • jti (JWT ID) – eindeutige ID, z.B. für Revocation-Listen

Mindestens exp solltest Du immer setzen. Ohne exp ist ein gestohlener Token unbegrenzt gültig.

Sicherheits-Pitfalls

1. alg: none

Frühere Bibliotheken akzeptierten Tokens mit {"alg":"none"} ohne Signatur. Wenn Deine Library das noch tut: sofort patchen. Akzeptiere serverseitig immer nur einen festen Algorithmus, niemals den aus dem Header.

2. Algorithm-Confusion

Wenn der Server RS256 erwartet aber den Algorithmus aus dem Header übernimmt, kann ein Angreifer HS256 mit dem öffentlichen RSA-Key als Geheimnis signieren – und der Server akzeptiert es. Lösung: Algorithmus hart codieren.

3. Kein exp

Tokens ohne Ablauf sind ein Sicherheits-GAU. Standard sollte 15 Minuten bis 1 Stunde sein.

4. JWT in LocalStorage

Im LocalStorage abgelegte Tokens sind über jeden XSS-Bug abgreifbar. Besser: HttpOnly-Cookie mit Secure und SameSite=Lax oder Strict. Achte aber auf CSRF-Schutz.

5. Schwacher HMAC-Schlüssel

Mindestens 256 Bit (32 Byte) Zufall, niemals ein Passwort oder "secret". Tools wie openssl rand -base64 32 erledigen das in einer Zeile.

Best Practices

  1. Kurze Lifetime für Access-Tokens (5–60 Minuten).
  2. Lange Lifetime nur für Refresh-Tokens, und diese rotieren bei jeder Nutzung.
  3. Algorithmus hart codieren – nie aus dem Header übernehmen.
  4. HttpOnly-Cookie statt LocalStorage, oder Memory-only im SPA.
  5. JTI + Server-seitige Blacklist, wenn Du Revocation brauchst (sonst gilt der Token bis exp).
  6. Niemals sensible Daten im Payload – er ist nur kodiert, nicht verschlüsselt.