jwtdecoder.de

Ratgeber · JWT 2026

JWT-Sicherheit: 10 Regeln aus Production-Audits

Aus realen Pentests: alg whitelisten, kid-Header verifizieren, kurze Lifetimes, Refresh-Tokens rotieren, Secrets in Vault statt im Env-File.

Foto von Jan-Tristan Rudat

Von Jan-Tristan Rudat

Redakteur jwtdecoder.de

10 Regeln aus Production-Audits

Die folgende Liste ist eine Synthese aus Pentests und Code-Reviews der letzten Jahre. Jede Regel adressiert eine real beobachtete Schwachstelle in Production-Systemen.

1. alg explizit whitelisten

Niemals nur dem alg-Header vertrauen. Verifier-Code MUSS eine explizite Liste erlaubter Algorithmen führen. Bei JavaScript/jose: jwtVerify(token, key, { algorithms: ['RS256'] }). Bei Java/jose4j: setJwsAlgorithmConstraints(PERMIT, RS256). Bei Python/PyJWT: jwt.decode(token, key, algorithms=['RS256']).

2. alg=none ablehnen

Falls 1) richtig gemacht ist, ist 2) automatisch erfüllt. Aber für ältere Codebases lohnt ein expliziter Check. Siehe Case-Study alg=none aufgedeckt.

3. aud prüfen

Jeder Service-Verifier MUSS prüfen, dass sein eigener Identifier in aud steht. Ohne diese Prüfung können Tokens zwischen Services "wiederverwendet" werden - Service B akzeptiert ein Token, das für Service A ausgestellt wurde.

4. iss prüfen

Spiegelbild zu 3): Verifier MUSS prüfen, dass iss einen erwarteten Wert hat. Sonst akzeptiert er Tokens beliebiger fremder Issuer. Bei OAuth: gegen die Discovery-URL des erwarteten Providers prüfen.

5. Kurze Access-Token-Lifetimes

Access-Tokens: 5-15 Minuten. Refresh-Tokens: 7-30 Tage. Lange Lifetimes (Stunden bis Tage) sind ein Anti-Pattern, weil JWTs nicht ohne Weiteres revoziert werden können. Wenn ein Token kompromittiert wird, ist es bis exp gültig.

6. Refresh-Token-Rotation aktivieren

Jeder Refresh erneuert auch den Refresh-Token. Wenn ein Angreifer einen Refresh-Token stiehlt und benutzt, bekommt er einen neuen. Aber der echte User hat noch den alten - beim nächsten Refresh-Versuch fällt die Reuse auf, ganze Familie wird revoziert. Siehe Refresh-Rotation in Production.

7. Secrets nicht im Repository

JWT-Secrets gehören in Vault, KMS, AWS Secrets Manager, Azure Key Vault - niemals in das Git-Repo, niemals in .env-Files, die in den Build kommen. Bei HS256: mindestens 32 byte zufällig (z.B. openssl rand -base64 32).

8. Sensible Daten nicht im Payload

Payload ist base64url-encoded, NICHT verschlüsselt. Im JWT Decoder lesbar. Passwörter, Kreditkarten-Nummern, vollständige Adressen, Identitätsdokumente: alle gehören NICHT in den Payload. Erlaubt: User-ID, Rolle, Berechtigungen, allgemeine Profil-Felder.

9. JWKS richtig cachen

JWKS-Endpoint nicht bei jedem Request abrufen - Rate-Limit-Risiko bei Auth-Provider. Aber auch nicht für immer cachen: Key-Rotation muss durchschlagen. Typisch: 1-24 Stunden Cache, Cache-Control-Header respektieren, bei kid-Lookup-Miss einmal frisch laden. Siehe JWKS-Key-Rotation.

10. Algorithm-Confusion verhindern

Klassisches Szenario: Verifier erwartet RS256. Angreifer ändert alg auf HS256, signiert mit dem Public Key (den jeder kennt) als HMAC-Secret. Verifier benutzt den Public Key als HMAC-Verification-Key. Stimmt zufällig - und Angreifer hat gültiges Token. Fix: nicht nur alg whitelisten, sondern auch Key-Type prüfen. Bei manchen Libraries muss man explizit zwei separate Code-Pfade für HMAC vs Asymmetrisch trennen.

Bonus: kid sanitisieren

Der kid-Header ist user-controlled. Wenn der Verifier kid direkt in einen File-Path oder SQL-Query einsetzt, sind Path-Traversal und SQL-Injection echte Angriffsvektoren. Strikte Whitelist (z.B. nur alphanumerisch + Bindestrich) oder Hash-basiertes Lookup.

Bonus: Negative Tests in CI

Standard-Unit-Tests prüfen, dass gültige Tokens akzeptiert werden. Negative Tests sind genauso wichtig:

  • Token mit alg=none wird abgelehnt
  • Token mit alg=HS256, aber unter Verwendung des Public Keys als Secret signiert, wird abgelehnt
  • Token mit falschem aud wird abgelehnt
  • Token mit falschem iss wird abgelehnt
  • Abgelaufenes Token wird abgelehnt (exp in der Vergangenheit)
  • Token mit nbf in der Zukunft wird abgelehnt

Diese Tests sollten in CI laufen - Library-Updates können Defaults ändern, und ohne automatisierte Negativ-Tests merkt man Regressions oft erst beim nächsten Pentest.

Die OWASP-JWT-Cheat-Sheet (owasp.org) und der IETF-Draft draft-ietf-oauth-security-topics sind die kanonischen Quellen für vertiefende Lektüre.

Mehr zum Thema