JWT-Signatur gegen ein JWKS prüfen, ohne Backend

JWT-Signatur gegen ein JWKS prüfen, ohne Backend

Fügen Sie Token und JWKS ein und prüfen Sie eine RS256-, ES256- oder HS256-Signatur im Browser. Schlüsselwahl per kid, Fehler und zu prüfende Claims.

26.10.2026
13 Min. Lektüre
Teilen Sie diesen Artikel:
JWTjwksoidcSicherheitAnleitung

Eine Signaturprüfung braucht das Token und den richtigen öffentlichen Schlüssel

Wer ein JWT dekodiert, sieht, was es behauptet. Wer es prüft, sieht, ob der erwartete Schlüssel diese Angaben signiert hat. Bei einem OpenID-Connect-Anbieter wie Auth0, Keycloak oder Cognito liegt dieser Schlüssel in einem JWKS, einem JSON-Dokument mit öffentlichen Schlüsseln. Dieser Leitfaden zeigt, wie der Prüfer einen Schlüssel auswählt und wie Sie seine Antwort lesen, wenn eine Integration scheitert. Grundlage ist das JWT-Verify-Tool. Es nimmt das JWKS als eingefügten Text und ruft nie eine Adresse ab, sodass kein Server nötig ist. Am 26. Oktober 2026 haben wir 31 Testfälle durch den Code des Prüfers geschickt und berichten jedes Ergebnis. Sie umfassen Tokens mit RS256, ES256 und HS256 sowie veränderte, abgelaufene und falsch zugeordnete. Die Regeln stammen aus den RFC 7515, 7517, 7518, 7519 und 8725. Wenn Sie ein Token erst lesen möchten, beginnen Sie mit unserem Leitfaden zum Erstellen und Dekodieren von JWTs.

Dekodieren liest ein Token. Prüfen vergleicht seine Signatur mit einem öffentlichen Schlüssel aus dem JWKS.
Der Header kid wählt den Schlüssel. Er ist ein Hinweis und optional (RFC 7515, Abschnitt 4.1.4).
Ein Token ohne kid wurde mit einem JWKS aus einem Schlüssel geprüft und scheiterte mit einem JWKS aus drei Schlüsseln.
Eine RS256-Signatur eines 2048-Bit-Schlüssels ist 256 Byte lang, eine ES256-Signatur 64 Byte.
Eine gültige Signatur sagt nicht, dass das Token für Ihre API bestimmt ist. Prüfen Sie auch iss, aud und exp.
Fügen Sie den Inhalt des JWKS ein, nicht seine Adresse. Das Tool lädt nichts nach.

Wie ein JWKS funktioniert und wie der Schlüssel gewählt wird

Ein JWKS ist eine JSON-Liste öffentlicher Schlüssel

RFC 7517 definiert ein JWK Set als Objekt mit einem Array keys. Die Reihenfolge der Schlüssel drückt keine Vorliebe aus, sofern die Anwendung nichts anderes festlegt. Jeder Schlüssel nennt seinen Typ in kty und trägt die Zahlen, die für die Prüfung nötig sind.

Verbesserungen

RSA-Schlüssel tragen n und e (Modul und Exponent). In unserem Test hatte der Wert n eines 2048-Bit-Schlüssels 342 Base64URL-Zeichen.
EC-Schlüssel tragen crv, x und y. Ein P-256-Schlüssel erzeugt ES256-Signaturen.
kid, alg und use sind optionale Angaben. use lautet sig zum Signieren oder enc zum Verschlüsseln.
Unser Testsatz (zwei RSA-Schlüssel und ein EC-Schlüssel, je mit kid, alg und use) umfasste 997 Zeichen, ein eingefügtes JWKS bleibt also klein.
Ein Schlüssel vom Typ oct enthält in k ein gemeinsames Geheimnis. Das ist privates Material, auch in einem Dokument namens Schlüsselsatz.
Die kid wählt den Schlüssel, und sie ist nur ein Hinweis

RFC 7515 nennt kid einen Hinweis darauf, welcher Schlüssel das Token gesichert hat, und der Header ist optional. Der Prüfer vergleicht ihn mit der kid jedes JWK. Was ohne Treffer geschieht, hängt vom Tool ab, deshalb haben wir es getestet.

Verbesserungen

Token mit kid k1 und ein Satz aus drei Schlüsseln, der k1 enthält: geprüft, und das Ergebnis nennt k1.
Token ohne kid und ein Satz aus drei Schlüsseln: kein passender Schlüssel, denn der Prüfer kann nicht raten.
Token ohne kid und ein Satz aus einem Schlüssel oder ein einzelnes JWK: geprüft.
Token mit kid a und ein einzelner Schlüssel ohne kid: kein passender Schlüssel. Eine Angabe auf nur einer Seite genügt nicht.
Token mit unbekannter kid: kein passender Schlüssel. In der Produktion deutet das meist auf eine Schlüsselrotation des Anbieters hin.
Größen und Formate von Signaturen

Das dritte Segment des Tokens ist die Signatur. Länge und Kodierung hängen vom Algorithmus ab, was manche Fehler erklärt, die wie Beschädigung aussehen.

Verbesserungen

RS256 mit einem 2048-Bit-Schlüssel ergab eine Signatur von 256 Byte, daher das lange dritte Segment eines RSA-Tokens.
ES256 ergab 64 Byte. RFC 7518 definiert sie als R und S zu je 32 Byte, hintereinander gesetzt.
RFC 7518 verlangt für ES256 einen Wert von 64 Oktetten. Eine DER-Signatur, wie OpenSSL sie ausgibt, ist daher erst nach einer Umwandlung eine gültige JWS-Signatur.
HS256-Signaturen sind 32 Byte lang, und zum Prüfen braucht es dasselbe gemeinsame Geheimnis, das sie erzeugt hat.
Was eine gültige Signatur beweist und was nicht

Eine gültige Signatur zeigt, dass der Inhaber des privaten Schlüssels diesen Header und diese Nutzdaten signiert hat. Sie zeigt nicht, dass das Token für Ihren Dienst gedacht oder noch aktuell ist.

Verbesserungen

Wir haben in einem gültigen Token sub auf admin geändert. Das Ergebnis lautete Signatur ungültig.
RFC 8725, Abschnitt 3.8, verlangt, dass die verwendeten Schlüssel zum Aussteller aus iss gehören.
In unserem Test scheiterten ein aud mit dem Wert other und ein iss mit https://evil.example als Claim-Fehler, obwohl die Signatur stimmte.
Ein seit 30 Sekunden abgelaufenes Token bestand mit 60 Sekunden Zeittoleranz und scheiterte mit 0.

Ein OIDC-Token ohne Server untersuchen

Token und JWKS-Inhalt beschaffen

Kopieren Sie das Zugriffs- oder ID-Token aus der fehlgeschlagenen Anfrage, ohne das Präfix Bearer. Holen Sie dann das JWKS beim Anbieter. Seine Adresse steht im Feld jwks_uri des Discovery-Dokuments, erreichbar unter der Adresse des Ausstellers plus /.well-known/openid-configuration.

Auth0 veröffentlicht den Satz unter https://IHRE_DOMAIN/.well-known/jwks.json.
Cognito nutzt https://cognito-idp.REGION.amazonaws.com/USER_POOL_ID/.well-known/jwks.json und signiert seine Tokens mit RS256.
Keycloak nutzt /realms/REALM/protocol/openid-connect/certs. Neuere Versionen setzen das alte Präfix /auth nicht mehr davor.
Öffnen Sie die Adresse im Browser oder mit curl, kopieren Sie den JSON-Inhalt und fügen Sie diesen Inhalt ein, nicht die Adresse.
Lesen Sie den Aussteller im Claim iss des Tokens und nehmen Sie die Adresse aus dessen Discovery-Dokument, statt sie fest einzutragen.
Festlegen, was Ihr Server prüfen muss

Dieselben Entscheidungen gelten im Tool und im Produktionscode. Legen Sie sie einmal in Ihrer Konfiguration fest und lesen Sie sie nie aus dem Token.

Lassen Sie nur erwartete Algorithmen zu, zum Beispiel RS256. RFC 8725, Abschnitt 3.1, ordnet die Liste der Algorithmen der Anwendung zu.
Vergleichen Sie iss mit der genauen Adresse des Ausstellers.
Vergleichen Sie aud mit der Kennung Ihrer API.
Erlauben Sie eine kleine Zeittoleranz. RFC 7519 spricht von höchstens wenigen Minuten, und das Tool bietet 0, 60 oder 300 Sekunden.
Laden Sie das zwischengespeicherte JWKS neu, wenn ein Token eine kid trägt, die Sie nicht kennen.

Die Antwort des Prüfers lesen

Kein passender Schlüssel

Das Tool antwortet key_not_found, wenn das Token keine kid hat und der Satz mehrere Schlüssel enthält. Es antwortet auch so, wenn seine kid im Satz fehlt.

Dekodieren Sie das Token mit dem JWT-Dekodierer und vergleichen Sie die kid im Header mit den kid-Werten des eingefügten Satzes. Groß- und Kleinschreibung zählt.
Bei mehreren Schlüsseln und ohne kid im Token kann der Prüfer nicht wählen. Fügen Sie nur den erwarteten Schlüssel ein oder bitten Sie den Aussteller, kid zu setzen.
Eine unbekannte kid deutet auf eine Rotation beim Anbieter hin. Die Cognito-Dokumentation rät dann, die zwischengespeicherten Schlüssel neu zu laden.
Ein vor der Rotation kopierter Satz enthält den neuen Schlüssel nicht. Kopieren Sie den Inhalt beim Anbieter erneut.
Ungültige Signatur

Das Tool hat einen Schlüssel gefunden, und die Prüfung ist gescheitert. Mehrere Ursachen führen zur selben Meldung.

Veränderte Nutzdaten scheitern. Das Ändern von sub in einem gültigen Token ergab Signatur ungültig.
Ein Token, dessen kid auf Schlüssel B zeigt, das aber Schlüssel A signiert hat, scheitert genauso. Suchen Sie zwei Umgebungen mit verschiedenen Sätzen, etwa Staging und Produktion.
Ein privates JWK ergab Signatur ungültig, mit dem Hinweis, dass der Schlüssel öffentlich sein muss. Fügen Sie den öffentlichen Teil ein und prüfen Sie den Satz zuerst im Inspektor.
Ein Schlüssel eines anderen Typs als der Algorithmus, etwa ein EC-Schlüssel mit einem RS256-Token, endet ebenfalls hier.
Das Tool lehnt die Eingabe ab

Manche Antworten kommen vor jeder Signaturprüfung.

Ungültige JWT-Struktur: Das Token trägt noch sein Präfix Bearer. In unserem Test hat das Tool es nicht entfernt. Ein Zeilenumbruch am Ende störte nicht.
Ungültiges JWK- oder JWKS-JSON: eine Adresse statt des Inhalts, eine abgeschnittene Kopie oder ein leeres Array keys.
Nicht unterstützter Algorithmus bei alg none: Ein unsigniertes Token lässt sich nicht prüfen, und Ihr Server sollte es ebenfalls ablehnen.
Geheimnis erforderlich: Das Token nennt HS256, und der Satz enthält nur öffentliche RSA-Schlüssel. HMAC braucht ein gemeinsames Geheimnis oder einen oct-Schlüssel.

Vier Fehler bei der Prüfung mit einem JWKS

Eine gültige Signatur für eine Berechtigung halten

Die Signatur beweist, wer das Token ausgestellt hat. Sie sagt nichts darüber, was sein Inhaber in Ihrem Dienst darf.

Jedes vom Anbieter signierte Token annehmen, gleich für welche Zielgruppe.
Die Prüfung von iss überspringen, weil das JWKS schon vom Aussteller stammt.
Das grüne Ergebnis als Autorisierung lesen.
Ein Token, das für eine andere API desselben Anbieters ausgestellt wurde, besteht die Signaturprüfung und wird angenommen.
Prüfen Sie Signatur, iss, aud und exp gemeinsam und wenden Sie danach Ihre eigenen Zugriffsregeln an.
Material eines privaten Schlüssels einfügen

Ein JWK mit d oder ein oct-Schlüssel mit k ist ein Geheimnis. Ein Satz öffentlicher Schlüssel braucht beides nie.

Ein JWK, das noch d enthält, in einen Chat, ein Ticket oder ein Online-Tool einfügen.
Einen Satz aus einem Secret-Speicher statt vom öffentlichen Endpunkt kopieren.
Ein Test-JWKS mit seinen privaten Feldern einchecken.
Unser Test mit einem privaten RSA-JWK scheiterte nur, weil die Bibliothek einen öffentlichen Schlüssel verlangte. Dasselbe Einfügen an anderer Stelle könnte d preisgeben.
Öffnen Sie den Satz zuerst im JWKS-Inspektor. Seine Ansicht Inventar zeigt hasPrivate je Schlüssel, und die formatierte Ansicht entfernt d, die RSA-Faktoren und das k von oct-Schlüsseln.
Das Token den Algorithmus wählen lassen

Der Header alg gehört dem Absender. Folgt der Prüfer ihm, wählt der Angreifer die Prüfung.

Keine Option algorithms übergeben und dem Header alg vertrauen.
Einen öffentlichen RSA-Schlüssel als Geheimnis eines HS256-Tokens verwenden.
alg none auf einer Testroute zulassen, die in die Produktion gelangt.
Der Prüfer von FastMinify übernimmt bei einem einzelnen Schlüssel das alg des Tokens. In unserem Test prüfte ein als RS512 gekennzeichneter Schlüssel ein RS256-Token, und ein Schlüssel mit use auf enc ebenfalls. Produktionscode sollte strenger sein.
Legen Sie die Algorithmen in Ihrer Konfiguration fest. Nutzen Sie eine Bibliothek, die alg, use und key_ops abgleicht, wie jose es tut.
Das JWKS bei jeder Anfrage laden oder nie wieder

Beide Extreme scheitern. Das eine fügt jeder Anfrage einen Netzwerkaufruf hinzu, das andere sperrt Nutzer bei der ersten Rotation aus.

Den JWKS-Endpunkt für jedes Token aufrufen.
Den Satz für immer zwischenspeichern.
Einen Schlüssel fest eintragen statt des Satzes.
jose behält Schlüssel standardmäßig 10 Minuten und lädt bei einer unbekannten kid erst nach einer Wartezeit von 30 Sekunden neu.
Nutzen Sie eine Bibliothek, die zwischenspeichert und bei unbekannter kid neu lädt, und stellen Sie ihre Grenzen bewusst ein.

Vier Annahmen über JWKS und Signaturen

Die kid beweist, welcher Schlüssel das Token signiert hat

Die Angabe stammt vom Absender und beweist allein nichts.

Falsch. RFC 7515 nennt kid einen Hinweis. In unserem Test ergab ein Token mit kid k2, das Schlüssel k1 signiert hatte, Signatur ungültig.
Ein JWKS ist ein geheimes Dokument

Viele zögern, eines in ein Tool einzufügen.

Ein Satz öffentlicher Schlüssel ist von Anfang an öffentlich, und jeder kann ihn abrufen. Die Ausnahme ist der oct-Schlüssel, dessen Wert k ein gemeinsames Geheimnis ist, das Sie nie veröffentlichen dürfen.
ES256-Signaturen sind ASN.1 DER, wie bei OpenSSL

Dieser Glaube führt zu Umwandlungscode, den ein JWT nicht braucht.

Falsch. RFC 7518 verlangt einen Wert von 64 Oktetten aus R und S. Unser ES256-Testtoken hatte eine Signatur von 64 Byte.
Für die Prüfung eines JWT braucht man ein Backend

Die Vorstellung stammt von Bibliotheken, die Schlüssel auf einem Server laden und zwischenspeichern.

Nein. Ein JWKS sind öffentliche Daten, und die Prüfung ist eine lokale Berechnung. Die Prüfseite arbeitet mit eingefügtem Text in Ihrem Browser und lädt keine Schlüssel nach.

Im Browser prüfen und untersuchen

Ein Token gegen ein JWKS prüfen

Das JWT-Verify-Tool prüft die Signatur und, auf Wunsch, Zielgruppe, Aussteller und Zeit-Claims. Es unterstützt 14 Algorithmen, darunter RS256, ES256 und HS256.

1

Token einfügen

Fügen Sie zuerst das kompakte JWT ein. Die Schlüssel-Tabs folgen dem alg aus seinem Header.

2

JWKS-Inhalt einfügen

Fügen Sie das JSON des Schlüsselsatzes, ein einzelnes JWK oder ein öffentliches PEM ein. Um einen PEM-Schlüssel vorher in ein JWK umzuwandeln, nutzen Sie den PEM-JWK-Konverter. Bei einem HS256-Token verwenden Sie den Tab HMAC-Secret.

3

Prüfungen einstellen

Geben Sie Zielgruppe und Aussteller ein, wenn sie verglichen werden sollen, und wählen Sie eine Zeittoleranz von 0, 60 oder 300 Sekunden. Die Option Ablauf ignorieren prüft die Signatur trotzdem.

4

Ergebnis lesen

Das Ergebnis zeigt gültig mit Algorithmus und kid oder einen Fehlercode, der oben im Abschnitt zur Fehlersuche beschrieben ist.

Zuerst den Schlüsselsatz ansehen

Der JWKS-Inspektor liest ein JWK oder JWKS, ohne etwas zu prüfen. Nutzen Sie ihn vor dem Prüfer, wenn ein Satz von jemand anderem stammt.

1

JWKS einfügen

Fügen Sie einen Schlüsselsatz oder einen einzelnen Schlüssel ein. Private Felder werden aus Ausgabe und Kopie entfernt.

2

Zur Ansicht Inventar wechseln

Das Inventar listet kid, kty, use, alg, crv und hasPrivate je Schlüssel auf, ohne Schlüsselmaterial auszugeben.

3

Schlüssel sortieren

Die Option Schlüssel sortieren ordnet das JSON, damit sich zwei Umgebungen per Diff vergleichen lassen.

Was die Tools nicht tun

Beide Seiten arbeiten mit eingefügtem Text. Einige Grenzen sollten Sie kennen.

Kein Abruf einer JWKS-Adresse: Sie fügen den Inhalt ein.
Keine verschlüsselten Tokens (JWE): nur signierte mit drei Teilen.
Das Tool liest den Algorithmus aus dem Token und vergleicht ihn bei einem einzelnen Schlüssel nicht mit dessen alg.
Geprüft heißt nicht vertrauenswürdig: Das Tool weiß nicht, ob der Aussteller Ihr Vertrauen verdient.
Jedes Feld ist auf 512 KB begrenzt.

Dieselben Prüfungen im Terminal und in Ihrem Code

Die Schlüssel eines Anbieters mit curl und jq auflisten

Ersetzen Sie die Adresse durch Ihren Aussteller. Der letzte Befehl liest die kid aus dem ersten Segment eines Tokens in der Variablen TOKEN.

Einfaches Beispiel

# jwks_uri aus dem Discovery-Dokument lesen curl -s https://auth.example.com/.well-known/openid-configuration | jq -r .jwks_uri # Schlüssel auflisten: kid, Typ, Algorithmus und Verwendung curl -s https://auth.example.com/.well-known/jwks.json | jq -c '.keys[] | {kid, kty, alg, use}' # kid im Header des Tokens lesen echo "$TOKEN" | jq -R 'split(".")[0] | gsub("-";"+") | gsub("_";"/") | @base64d | fromjson | .kid'
Mit jose und einem entfernten JWKS prüfen

createRemoteJWKSet lädt den Satz, speichert ihn zwischen und wählt den Schlüssel nach kid und alg. Algorithmus, Aussteller und Zielgruppe kommen aus Ihrer Konfiguration.

Einfaches Beispiel

import { createRemoteJWKSet, jwtVerify } from 'jose' const jwks = createRemoteJWKSet(new URL('https://auth.example.com/.well-known/jwks.json')) const { payload, protectedHeader } = await jwtVerify(token, jwks, { algorithms: ['RS256'], // von Ihnen festgelegt, nie aus dem Token gelesen issuer: 'https://auth.example.com', audience: 'orders-api', clockTolerance: 60, // Toleranz, als Sekundenwert }) console.log(protectedHeader.kid, payload.sub)
Mit einem eingefügten JWKS prüfen, wie es das Tool tut

createLocalJWKSet nimmt den Satz, den Sie schon haben. In unseren Tests warf es ERR_JWKS_NO_MATCHING_KEY bei unbekannter kid. Es warf ERR_JWKS_MULTIPLE_MATCHING_KEYS bei einem Token ohne kid und zwei RSA-Schlüsseln. Es warf ERR_JOSE_ALG_NOT_ALLOWED, wenn die Liste der Algorithmen das alg des Tokens ausschloss.

Einfaches Beispiel

import { createLocalJWKSet, jwtVerify } from 'jose' // jwksText ist der JSON-Text, den Sie beim Anbieter kopiert haben const jwks = createLocalJWKSet(JSON.parse(jwksText)) try { const { payload, protectedHeader } = await jwtVerify(token, jwks, { algorithms: ['RS256'], issuer: 'https://auth.example.com', audience: 'orders-api', clockTolerance: 60, }) console.log(protectedHeader.kid, payload.sub) } catch (err) { // ERR_JWKS_NO_MATCHING_KEY, ERR_JWS_SIGNATURE_VERIFICATION_FAILED, ERR_JWT_CLAIM_VALIDATION_FAILED, ERR_JWT_EXPIRED console.error(err.code) }

Zusammenfassung

Die Prüfung mit einem JWKS läuft auf drei Entscheidungen hinaus. Wählen Sie den Schlüssel per kid und alg. Prüfen Sie iss, aud und exp. Fehlt der Schlüssel, laden Sie den Satz neu, statt dem Token zu vertrauen. Mit den Browser-Tools lässt sich jeder Fall mit eingefügtem Text nachstellen, bevor Sie einen Server anfassen. Sehen Sie den Satz an, prüfen Sie das Token und übernehmen Sie dieselben Einstellungen in Ihren Code.

Probieren Sie die Schlüssel-Tools im Browser aus

Dekodieren Sie zuerst das Token und vergleichen Sie seine kid mit dem Satz, bevor Sie die Signatur verdächtigen.
Sehen Sie jedes JWKS an, das Sie nicht selbst erzeugt haben, und prüfen Sie hasPrivate, bevor Sie es irgendwo einfügen.
Legen Sie Algorithmus, Aussteller und Zielgruppe in Ihrer Konfiguration fest.
Speichern Sie das JWKS zwischen und laden Sie es neu, wenn ein Token eine unbekannte kid trägt.
Verstehen Sie eine gültige Signatur als erste Prüfung, nicht als Berechtigung.
Teilen Sie diesen Artikel
Teilen Sie diesen Artikel: