jwtdecoder.de

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.

Foto von Mateusz Viola

Von Mateusz Viola

Betreiber & redaktionelle Verantwortung jwtdecoder.de

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

FeldBedeutung
ktyKey Type: "RSA", "EC", "oct" (für HMAC, aber selten in JWKS), "OKP" (für EdDSA)
algAlgorithmus, für den der Key bestimmt ist: "RS256", "ES256" etc.
kidKey ID - eindeutige Bezeichnung innerhalb des Sets
use"sig" für Signatur-Verifikation, "enc" für Verschlüsselung
n, eRSA-spezifisch: Modulus und Public Exponent
x, y, crvEC-spezifisch: X-Koordinate, Y-Koordinate, Kurve ("P-256", "P-384", "P-521")

Verifier-Workflow

  1. JWT empfangen, Header parsen, kid auslesen
  2. JWKS für den iss-Issuer holen (aus Cache oder live)
  3. JWK mit passendem kid in der "keys"-Liste finden
  4. Public Key aus dem JWK konstruieren (Library-spezifisch - meist jwkToPem(jwk) oder ähnlich)
  5. 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:

  1. Tag -2: Neuen Key generieren (RSA-2048 oder EC P-256), beide Keys in den Vault/KMS.
  2. 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.
  3. Tag 0: Issuer wechselt zum neuen Key (alle neuen Tokens haben neuen kid). Alte Tokens bleiben gültig (alter Key noch im JWKS).
  4. Tag 30: Alle Tokens, die mit altem Key signiert wurden, sind abgelaufen (typisch Refresh-Token-Lifetime). Alter Key kann aus JWKS entfernt werden.
  5. 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.

Mehr zum Thema