Ratgeber · JWT 2026
JWKS - der Standard für Public-Key-Verteilung
JWKS-Endpoint-Format nach RFC 7517, Caching-Header beachten, kid-Lookup im JWT-Header, Rotation transparent für Clients.
Von Mateusz Viola
Betreiber & redaktionelle Verantwortung jwtdecoder.de
Veröffentlicht
Aktualisiert:
JWKS in einem Satz
JWKS (JSON Web Key Set, RFC 7517) ist ein JSON-Dokument mit einer Liste von Public Keys, die ein OAuth-Provider oder Token-Issuer bereitstellt. Verifier laden das Dokument und können damit Token-Signaturen prüfen, ohne dass Secrets zwischen Issuer und Verifier ausgetauscht werden müssen.
Wie ein JWKS-Endpoint aussieht
Standardpfad: /.well-known/jwks.json auf der Domain des Issuers. Beispiel von Google:
GET https://www.googleapis.com/oauth2/v3/certs
{
"keys": [
{
"kty": "RSA",
"alg": "RS256",
"kid": "abc123def456",
"use": "sig",
"n": "0vx7agoebGcQSuuPiLJXZptN9...",
"e": "AQAB"
},
{
"kty": "RSA",
"alg": "RS256",
"kid": "old789xyz012",
"use": "sig",
"n": "lOVOmtMl0lFs6CrhppdRr...",
"e": "AQAB"
}
]
}
Mehrere Keys parallel - typisch für die Overlap-Phase einer Key-Rotation.
Felder eines JWK
| Feld | Bedeutung |
|---|---|
| kty | Key Type: "RSA", "EC", "oct" (für HMAC, aber selten in JWKS), "OKP" (für EdDSA) |
| alg | Algorithmus, für den der Key bestimmt ist: "RS256", "ES256" etc. |
| kid | Key ID - eindeutige Bezeichnung innerhalb des Sets |
| use | "sig" für Signatur-Verifikation, "enc" für Verschlüsselung |
| n, e | RSA-spezifisch: Modulus und Public Exponent |
| x, y, crv | EC-spezifisch: X-Koordinate, Y-Koordinate, Kurve ("P-256", "P-384", "P-521") |
Verifier-Workflow
- JWT empfangen, Header parsen, kid auslesen
- JWKS für den iss-Issuer holen (aus Cache oder live)
- JWK mit passendem kid in der "keys"-Liste finden
- Public Key aus dem JWK konstruieren (Library-spezifisch - meist
jwkToPem(jwk)oder ähnlich) - Signature mit dem Key verifizieren
Caching: das Daumenregel-Setup
JWKS bei jedem Token-Verify abzurufen wäre Rate-Limit-Wahnsinn. JWKS-Caching ist Pflicht - aber die Cache-TTL muss zur Rotation-Frequenz passen.
- Production Default: 1-6 Stunden TTL. Cache-Control-Header des Issuers respektieren wenn vorhanden.
- Lazy-Refresh: bei kid-Lookup-Miss einmal frisch laden (Rotation just happened, Cache hatte den neuen Key noch nicht).
- Niemals 0-TTL: das wäre Rate-Limit-Risiko, Auth-Provider blockieren oder fangen an zu drosseln.
- Niemals unendliche TTL: dann sieht der Verifier rotierten Keys nie.
JWKS selbst hosten
Wer einen eigenen Auth-Service betreibt und JWKS herausgibt: kein Hexenwerk. Endpunkt mit Cache-Control-Header:
GET /.well-known/jwks.json
Cache-Control: public, max-age=3600
Content-Type: application/json
{
"keys": [...]
}
JSON-Generierung aus dem aktuellen Key-Material: die meisten Crypto-Libraries haben einen "publicKeyToJWK"-Helper. In Node.js mit jose: publicKeyToJWK(key). In Python mit jwcrypto: JWK.from_pem(...).export_public().
Rotation in der Praxis
Beim Schlüsselwechsel:
- Tag -2: Neuen Key generieren (RSA-2048 oder EC P-256), beide Keys in den Vault/KMS.
- Tag -1: Neuen Key zum JWKS hinzufügen, alter Key bleibt drin. Issuer signiert weiter mit altem Key. Caches haben jetzt Zeit, sich zu aktualisieren.
- Tag 0: Issuer wechselt zum neuen Key (alle neuen Tokens haben neuen kid). Alte Tokens bleiben gültig (alter Key noch im JWKS).
- Tag 30: Alle Tokens, die mit altem Key signiert wurden, sind abgelaufen (typisch Refresh-Token-Lifetime). Alter Key kann aus JWKS entfernt werden.
- Tag 31: Alter Key wird aus Vault gelöscht. Rotation abgeschlossen.
OIDC-Discovery
OpenID-Connect-Provider exposen zusätzlich /.well-known/openid-configuration, das auf das JWKS verweist:
GET https://accounts.google.com/.well-known/openid-configuration
{
"issuer": "https://accounts.google.com",
"authorization_endpoint": "...",
"token_endpoint": "...",
"jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
"id_token_signing_alg_values_supported": ["RS256"],
...
}
Verifier-Code muss nicht den JWKS-URL hardcoden - Discovery liefert ihn dynamisch. Best-Practice für Verifier: bei Start einmal die Discovery laden, JWKS-URL extrahieren, dann periodisch JWKS refresh.
Häufige Fehler
- kid wird nicht beim Lookup verwendet: Verifier nimmt einfach den ersten Key der Liste. Funktioniert solange nur ein Key da ist - bei Rotation bricht es.
- JWKS-Caching ignoriert: jedes Token-Verify ruft JWKS frisch ab. Rate-Limit-Risiko.
- Kein Lazy-Refresh: nach Rotation lehnen Verifier alle neuen Tokens ab, bis TTL abläuft.
- HTTP statt HTTPS: JWKS-URL muss HTTPS sein, sonst MITM-Angriffsfläche.
Im JWT Decoder kann der Public Key direkt eingegeben werden - entweder als PEM-String aus dem JWKS extrahiert (siehe jwkToPem-Helper in den meisten Libraries) oder als ganzer JWK-JSON. Verifikation läuft über die Web Crypto API direkt im Browser.