Bei invalid signature, signature verification failed oder einer ungültigen JWT-Signatur ändere ich weder Payload noch Verifier-Konfiguration auf Verdacht. Ich sichere das originale kompakte Token und prüfe deterministisch: Algorithmus, exakte Key-Bytes, Issuer, kid, Rotation und erst dann Claims.
Mit bekanntem Secret/Public Key starte ich im JWT Signature Verifier. Bei JWKS nutze ich den JWKS Validator.
Was „invalid signature“ präzise bedeutet
Ein kompaktes JWS hat:
base64url(header).base64url(payload).base64url(signature)
Verifikation verwendet die original codierten ersten beiden Segmente. Wenn sie scheitert, stimmen mindestens Algorithmus, Schlüssel oder signierte Bytes nicht mit dem Signer überein.
Der Fehler sagt dagegen nicht automatisch etwas über exp, aud oder Berechtigungen aus.
Mein erster Split: HMAC oder asymmetrisch?
Header:
{ "alg": "HS256", "kid": "optional" }
oder:
{ "alg": "RS256", "kid": "prod-2026-09" }
Meine Diagnose verzweigt sofort:
HS256/384/512 -> Secret-Bytes, Encoding, Rotation
RS256/384/512 -> Public Key, PEM/JWK, kid, JWKS, Issuer
Ich lasse das Token nicht selbst die Policy festlegen. Die Anwendung hat eine Algorithmus-Allowlist.
HMAC: gleiche Zeichenfolge bedeutet nicht zwingend gleiche Bytes
Bei HS256 prüfe ich besonders:
- UTF-8-Text vs. Base64-dekodiertes Secret;
- verstecktes
\nam Ende einer Environment Variable; - unterschiedliche Secrets in Dev/Prod;
- Secret Rotation;
- Copy/Paste mit Leerzeichen;
- zu schwache, menschenlesbare Secrets.
Beispiel:
const raw = new TextEncoder().encode(process.env.JWT_SECRET);
const fromBase64 = Uint8Array.from(atob(process.env.JWT_SECRET), c => c.charCodeAt(0));
// raw und fromBase64 sind nicht dasselbe Key-Material.
Ich kläre zuerst, welche Interpretation der Signer verwendet.
RSA: PEM, Zertifikat und SPKI auseinanderhalten
Bei RS256 kann „falscher Key“ auch ein Formatproblem sein. Ich prüfe:
-----BEGIN PUBLIC KEY----- -> häufig SPKI
-----BEGIN CERTIFICATE----- -> X.509 Zertifikat
-----BEGIN RSA PUBLIC KEY----- -> PKCS#1 Public Key
Libraries akzeptieren nicht jede Form identisch. Ich konvertiere kontrolliert statt Header/Footer blind zu löschen.
kid und JWKS als Auswahlproblem debuggen
Wenn der Token Header kid enthält, suche ich im vertrauenswürdigen JWKS des erwarteten Issuers. Häufige Ursachen:
kidfehlt im gecachten JWKS;- neuer Key wurde veröffentlicht, Cache ist alt;
- alter Key wurde zu früh entfernt;
- falscher Tenant/Issuer;
kidtrifft auf inkompatiblenktyoderalg;- mehrere Keys erzeugen Ambiguität.
Der JWT-kid-Guide vertieft die Auswahl; der Key-Rotation-Guide den Lifecycle.
Exakte Fehlertexte richtig zuordnen
Typische Library-Meldungen sind:
JsonWebTokenError: invalid signature
JWSSignatureVerificationFailed
signature verification failed
InvalidSignatureError
kid not found
no applicable key found in the JSON Web Key Set
kid not found ist streng genommen noch vor der Kryptografie ein Key-Selection-Fehler. Ich werfe ihn nicht in denselben Topf wie eine tatsächlich berechnete, aber falsche Signatur.
Warum Re-Encoding einen Vergleich zerstören kann
Ich verifiziere das Originaltoken. Ich dekodiere nicht JSON, serialisiere es „schön“ neu und erwarte dieselbe Signatur.
Diese Payloads können semantisch gleich aussehen:
{"sub":"42","role":"user"}
{ "role": "user", "sub": "42" }
aber unterschiedliche Bytes erzeugen. JWS signiert Bytes des compact serialization input, nicht die semantische Bedeutung eines JSON-Objekts.
Eine gültige Signatur ist erst der Anfang der Acceptance
Wenn die Signatur passt, prüfe ich weiterhin:
exp/nbf;- erwarteten
iss; - erwarteten
aud; - Token-Typ;
- anwendungsspezifische Scopes/Rollen.
Dafür nutze ich den JWT Validator oder JWT Debugger.
Was ich niemals als „Fix“ akzeptiere
- Verification ausschalten;
- beliebigen Algorithmus aus dem Header akzeptieren;
- Key von einer untrusted
jku/URL laden und automatisch vertrauen; - Payload editieren und alte Signatur weiterverwenden;
- beim ersten
kid-Treffer alle Metadaten ignorieren; - weak HMAC Secret wählen, nur damit beide Seiten denselben String kennen.
Meine Entscheidungsmatrix
| Symptom | Wahrscheinliche Schicht | Prüfen |
|---|---|---|
| HS256 invalid signature | Secret/Encoding | exakte Bytes, Base64, Newline |
| RS256 invalid signature | Public Key/Format | Issuer-Key, PEM/JWK |
kid not found | Auswahl/Cache | JWKS, Rotation, Environment |
| Algorithm mismatch | Policy | erlaubter alg, Key-Typ |
| nach Payload-Edit Fehler | signed bytes | Originaltoken verwenden |
| Signatur ok, trotzdem 401 | Claims | exp/iss/aud/Token-Typ |
Mein Invalid-Signature-Workflow
- Ich sichere das originale compact JWT unverändert.
- Ich dekodiere Header
algundkidsowie Payloadiss. - Ich bestätige die erlaubte Algorithmus-Policy der Anwendung.
- Ich bestimme die vertrauenswürdige Key-Quelle für diesen Issuer.
- Bei HMAC vergleiche ich die exakten Secret-Bytes und deren Encoding.
- Bei RSA/EC prüfe ich Key-Format, Key-Typ und Provenienz.
- Bei JWKS prüfe ich
kid, Cache und Rotation. - Ich verifiziere über die originalen
header.payload-Bytes. - Erst nach erfolgreicher Signatur prüfe ich Zeit, Issuer und Audience.
- Ich behebe die falsche Key-/Policy-/Deployment-Schicht, nicht die Sicherheitsprüfung.
Invalid signature ist ein Vertrauensfehler, kein kosmetischer Parsing-Fehler. Genau diese Trennung macht die Diagnose reproduzierbar.