Ratgeber · JWT 2026
JWT debuggen: typische Fehler und schnelle Fixes
Wie man Token-Probleme schnell isoliert: Header decodieren, Algorithmus prüfen, exp/nbf gegen Server-Uhrzeit, Secret-Encoding (UTF-8 vs Base64).
Von Mateusz Viola
Betreiber & redaktionelle Verantwortung jwtdecoder.de
Veröffentlicht
Aktualisiert:
Acht typische Fälle
Beim Arbeiten mit JWT tauchen immer wieder die gleichen Probleme auf. Folgende Liste hilft, Token-Bugs schnell zu isolieren.
1. "Invalid Signature" trotz richtigem Secret
Häufigste Ursache: Secret-Encoding-Mismatch. HMAC braucht Bytes - aber wie der String-zu-Bytes-Konvert läuft, ist library-spezifisch.
- UTF-8: einfach
"my-secret"als UTF-8 interpretieren - Base64:
"bXktc2VjcmV0"erst base64-decoden, dann als Bytes nutzen - Hex:
"6d792d736563726574"als Hex parsen
Wenn Issuer das Secret als base64 hat und Verifier als UTF-8 interpretiert: Mismatch. Beide Seiten müssen das gleiche Encoding nutzen.
Tipp: Secrets immer als base64-encoded random bytes erzeugen (openssl rand -base64 32), Library mit base64-Decode konfigurieren.
2. "Token expired" obwohl gerade ausgestellt
Clock-Skew zwischen Servern. Issuer-Uhr ist 30 s vor, Verifier-Uhr ist normal. Issuer setzt exp = jetzt + 60 s, das landet beim Verifier als "vor 30 s abgelaufen".
Lösung: NTP-Sync auf allen Servern, Clock-Skew-Toleranz beim Verifier (±60 s ist Standard), exp-Lifetime nicht zu kurz wählen (mindestens 5 min, besser 10).
3. exp/iat sind Sekunden, nicht Millisekunden
JavaScript Date.now() liefert Millisekunden, JWT erwartet Sekunden. Häufiger Bug:
// FALSCH
const exp = Date.now() + 600 * 1000; // Millisekunden
// RICHTIG
const exp = Math.floor(Date.now() / 1000) + 600; // Sekunden
Mit Millisekunden gesetzt ist exp ein Wert in der fernen Zukunft (Jahr 2049+) - Token läuft 1000x später ab als gewollt. Mit Millisekunden bei Verify gegen Sekunden interpretiert ist exp "schon vor Jahrtausenden abgelaufen". Beides ist falsch.
4. Token-Whitespace beim Kopieren
Wer ein Token aus einem Email, Slack oder Browser-DevTools kopiert, kopiert oft Zeilenumbrüche, Leerzeichen oder unsichtbare Unicode-Zeichen mit. Base64url ist strikt - schon ein Leerzeichen am Ende macht die Signaturprüfung kaputt.
Tipp: vor dem Pasten trim() oder im Decoder visuell prüfen, ob das Token nur aus den Zeichen A-Z a-z 0-9 - _ . besteht.
5. alg-Header passt nicht zum Verifier
Issuer signiert mit HS256, Verifier konfiguriert ist für RS256. Library lehnt das Token ab, der Fehler kann unspezifisch sein ("Invalid Signature").
Tipp: ersten Schritt im Debugging: Header im JWT Decoder anschauen, alg-Wert prüfen. Mit Verifier-Erwartung abgleichen.
6. ECDSA-Signatur-Format-Konflikt
JOSE-Standard (RFC 7518) verlangt für ECDSA-Signaturen das raw R||S-Konkatenat: bei ES256 sind das 64 byte (R: 32 byte, S: 32 byte).
OpenSSL und viele Crypto-Libraries (Node.js's crypto, Java's java.security) liefern ECDSA-Signaturen aber als ASN.1-DER: variable Länge, ~70 byte.
Wer ein JWT mit OpenSSL-erzeugter Signatur baut, ohne sie in raw R||S zu konvertieren, produziert ein Token, das von JOSE-konformen Libraries abgelehnt wird. Library-spezifische Helper sind nötig.
7. Token in Base64, nicht Base64url
JWT verwendet base64url (RFC 4648 §5): Zeichen -_ statt +/, kein Padding. Wer mit klassischem base64 encodiert (mit +/=), produziert ein Token, das URL-Transport problematisch macht und das einige Libraries nicht parsen können.
Library-API auf base64url-Variante prüfen (in Node.js: Buffer.toString('base64url'), in Python: urlsafe_b64encode).
8. JWKS-Cache vergiftet
Verifier hat JWKS gecached, aber Issuer hat den Key rotiert. Neue Tokens haben kid, der im Cache nicht steht → "Key not found".
Lösung: JWKS-Cache-TTL korrekt setzen (typisch 1-6 h), bei kid-Miss einmal frisch nachladen. Siehe Key-Rotation.
Allgemeines Debugging-Vorgehen
- Token in jwtdecoder.de einfügen: Header und Payload werden als JSON gezeigt. Daraus alle wichtigen Infos ablesen - alg, kid, exp, iss, aud.
- exp-Check: Decoder zeigt automatisch ob abgelaufen.
- Signatur-Verifikation: mit dem erwarteten Secret/Public Key im Decoder testen. Falls Decoder grünen Badge zeigt, aber Production-Verifier ablehnt: das Problem liegt im Verifier-Code, nicht im Token.
- Server-Log: Verifier-Library hat meist sehr spezifische Error-Codes (e.g. "SignatureMismatchException"). Die exakte Exception ist wichtig - "Invalid Token" ist zu generisch.
- Vergleich zu Working-Token: ein bekannt-funktionierendes Token vom selben Issuer holen, Side-by-Side im Decoder ansehen. Welche Felder unterscheiden sich?
Test-Tokens für Lokal-Debugging
Im JWT Decoder kann man Test-Tokens direkt selbst signieren - Tab "Erstellen", Header und Payload editieren, Algorithmus und Secret wählen. Praktisch um schnell ein Token mit spezifischen Claims zu erzeugen und gegen den eigenen Verifier zu werfen.
Standard-Test-JWTs (klassisches jwt.io-Beispiel) sind nützlich als Smoke-Test:
// HS256 mit secret "your-256-bit-secret"
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c