
# Signierschlüssel rotieren

`POST /v1/signing-keys:rotate` · Berechtigung `signing-keys:write`

Führt sofort eine Rotation der Signierschlüssel außerhalb des automatischen Zeitplans aus.

- `mode: immediate`: Der reguläre Rotationsschritt wird sofort ausgeführt. Der vorab veröffentlichte `next`-Schlüssel beginnt mit dem Signieren, der alte `active`-Schlüssel bleibt `retired` für 7 Tage und ein neuer `next`-Schlüssel wird veröffentlicht. Verwendet `next` einen anderen Algorithmus als der aktive Schlüssel (ein Algorithmuswechsel) und wurde vor weniger als 7 Tagen veröffentlicht, schlägt der Aufruf mit `409 next_key_too_young` fehl.
- `mode: emergency` (vermutete Kompromittierung eines Schlüssels): Der alte `active`-Schlüssel wird widerrufen und verlässt das JWKS **sofort**; `next` wird aktiv und ein neuer `next` wird erzeugt. `revoke_next: true` widerruft außerdem `next` und aktiviert einen frisch erzeugten, noch nie veröffentlichten Schlüssel. `revoke_sessions: true` widerruft zudem jede Sitzung und jede Refresh-Token-Familie der Umgebung, sodass sich Benutzer erneut anmelden müssen. `reason` ist erforderlich.

## Föderationsschlüssel

Über `use` kann auch einer der Föderationsschlüssel der Umgebung angegeben werden: `saml_sp_signing` und `saml_sp_encryption` (die SAML-Signier- und Verschlüsselungsschlüssel des Service Providers, die in Ihren SP-Metadaten veröffentlicht werden) oder `oidc_rp_signing` (der `private_key_jwt`-Schlüssel von Enterprise-OIDC-Verbindungen, veröffentlicht unter `/sso/jwks.json`). Diese Schlüssel sind immer RSA-3072 und werden automatisch einmal pro Jahr rotiert: Ein neuer `next`-Schlüssel wird 30 Tage vor seiner Übernahme veröffentlicht, und der alte Schlüssel bleibt noch 30 Tage danach veröffentlicht.

- `mode: immediate` aktiviert den vorab veröffentlichten `next`-Schlüssel sofort; der alte Schlüssel bleibt weitere 30 Tage veröffentlicht (er erscheint in `retired_kids`). Ohne veröffentlichten `next`-Schlüssel schlägt der Aufruf mit `409 conflict` fehl; wurde der `next`-Schlüssel vor weniger als 7 Tagen veröffentlicht, mit `409 next_key_too_young`.
- `mode: emergency` entfernt den aktiven Schlüssel **sofort** aus den Metadaten bzw. dem JWKS und vernichtet seinen privaten Schlüssel (`revoked_kids`). Der veröffentlichte `next`-Schlüssel wird aktiv; gibt es keinen, oder mit `revoke_next: true`, übernimmt ein neuer, noch nie veröffentlichter Schlüssel diese Rolle. Identitätsanbieter, die Ihre Metadaten oder Ihr JWKS über die URL laden, übernehmen die Änderung bei ihrer nächsten Aktualisierung. Anbieter, bei denen Sie die Metadaten oder das Zertifikat manuell hochgeladen haben, lehnen Anmeldungen ab, bis Sie das neue Zertifikat hochladen; für diesen Fall wird für jede betroffene Verbindung ein `connection.sp_certificate_rotation_started`-Webhook-Ereignis gesendet.

Bei einem Föderationsschlüssel ist `next_kid` in der Antwort `null`, `removed_kids` ist leer und `revoke_sessions` ist nicht zulässig. Hat die Umgebung nie SAML oder `private_key_jwt` verwendet, gibt es keinen Schlüssel zum Rotieren, und der Aufruf schlägt mit `409 conflict` fehl.

### Verbindungsschlüssel

Eine SAML-Verbindung kann eigene, dedizierte SP-Schlüssel anstelle der Schlüssel der Umgebung haben. Um diese zu rotieren, fügen Sie `connection_id` (`conn_…`) mit `use: saml_sp_signing` oder `saml_sp_encryption` hinzu. Dieselben Modi, Berechtigungen und Regeln gelten, aber nur der Schlüsselsatz dieser Verbindung ändert sich: Die Schlüssel der Umgebung und die Schlüssel der übrigen Verbindungen bleiben unverändert, und das `connection.sp_certificate_rotation_started`-Ereignis wird nur für diese Verbindung gesendet. Der Audit-Eintrag nennt die Umgebung als Ziel und die Verbindung in `metadata.connection_id`. Eine unbekannte Verbindung oder eine Verbindung einer anderen Umgebung schlägt mit `404 not_found` fehl; eine Verbindung, die die Schlüssel der Umgebung verwendet, schlägt mit `409 connection_keys_not_dedicated` fehl (rotieren Sie die Schlüssel der Umgebung ohne `connection_id`). Ohne `connection_id` wird der Schlüsselsatz der Umgebung rotiert.

Der Notfallmodus benötigt neben `signing-keys:write` die ausdrücklich am Berechtigungsnachweis erteilte Berechtigung `signing-keys:emergency`: Nur ein eingeschränkter Schlüssel oder ein M2M-Client mit dieser Berechtigung kann ihn aufrufen. Ein geheimer Schlüssel mit vollem Zugriff (`idp_sk_…`) erhält im Notfallmodus `403 insufficient_permissions`.

Neue Token-Signierschlüssel verwenden den Algorithmus der Umgebungsrichtlinie ([Richtlinie abrufen](/docs/api/management/signing-keys/get-policy)). Eine erfolgreiche Rotation des Token-Signierschlüssels löst das Webhook-Ereignis `signing_key.rotated` oder `signing_key.revoked` aus; jede Rotation schreibt einen Verwaltungs-Audit-Eintrag. Dieser Endpunkt gehört zur Ratenbegrenzungsfamilie „Schlüssel- und Geheimnisausstellung“. Senden Sie einen `Idempotency-Key`: Ein erneuter Versuch nach einem Netzwerkfehler liefert dann das erste Ergebnis zurück, statt zweimal zu rotieren.

## Anfrage

JSON-Body (unbekannte Felder werden mit `400 unknown_field` abgelehnt):

| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
| `Idempotency-Key` | header | nein | Empfohlen. 16-64 Zeichen aus `A-Z a-z 0-9 _ -`. |
| `mode` | string | ja | `immediate` oder `emergency`. |
| `use` | string | nein | Der zu rotierende Schlüssel. Standard `token_signing` (Signierschlüssel für Zugriffs- und ID-Token). Die Föderationsschlüssel sind `saml_sp_signing`, `saml_sp_encryption` und `oidc_rp_signing` (siehe [Föderationsschlüssel](#föderationsschlüssel)). |
| `revoke_sessions` | boolean | nein | Nur für Notfall und `token_signing`. Widerruft außerdem alle Sitzungen und Refresh-Token. Standard `false`. |
| `revoke_next` | boolean | nein | Nur für Notfall. Widerruft außerdem den veröffentlichten `next`-Schlüssel. Standard `false`. |
| `reason` | string | Notfall: ja | Nur für Notfall. 1-512 druckbare ASCII-Zeichen, zum Beispiel eine Vorfallnummer. Geben Sie hier keine Geheimnisse oder personenbezogenen Daten ein. |
| `connection_id` | string | nein | Nur `saml_sp_signing` und `saml_sp_encryption`. Eine SAML-Verbindung (`conn_…`) mit dedizierten SP-Schlüsseln; ihr Schlüsselsatz wird anstelle des Satzes der Umgebung rotiert (siehe [Verbindungsschlüssel](#verbindungsschlüssel)). |

Bei `mode: immediate` schlägt das Senden von `revoke_sessions: true`, `revoke_next: true` oder eines `reason` mit `422` fehl (`not_allowed`). Ein `connection_id` mit `token_signing` oder `oidc_rp_signing` schlägt auf die gleiche Weise fehl.

## Antwort

`200 OK` mit dem Ergebnis der Rotation. `activated_kid` ist der Schlüssel, der ab jetzt signiert, und `next_kid` der neu veröffentlichte `next`-Schlüssel (`null` bei einem Föderationsschlüssel). `retired_kids` sind Schlüssel, die nicht mehr signieren und veröffentlicht bleiben (7 Tage für einen Token-Signierschlüssel, 30 Tage für einen Föderationsschlüssel); `revoked_kids` sind Schlüssel, die durch eine Notfallrotation aus dem JWKS entfernt wurden; `removed_kids` sind ausgemusterte Schlüssel, deren 7-Tage-Fenster abgelaufen ist und die im selben Schritt das JWKS verlassen haben.

```json
{
  "mode": "immediate",
  "use": "token_signing",
  "activated_kid": "ypeBEsobvcr6wjGzmiPcTaeG7_gUfE5yuYB3ha_uSLs",
  "next_kid": "GKw-c0PwFokMUQ6T-TUmEWnZ4_VlQ2Qpgw-vCTT0-OQ",
  "retired_kids": ["PiPoFgA5WUoziU9lZOGxNIu9egCI1CxKy3PurtWcAJ0"],
  "revoked_kids": [],
  "removed_kids": ["Ln0sA6lQeuJl7PW1NWiFpTOTogKdJBOUmXJloaJa78Y"],
  "revoke_sessions": false
}
```

## Fehler

| HTTP | Code | Wann |
|---|---|---|
| 400 | `unknown_field` | Der Body enthält ein unbekanntes Feld. |
| 400 | `malformed_request` | Der Body ist kein gültiges JSON, oder der Header `Idempotency-Key` ist fehlerhaft oder doppelt vorhanden. |
| 403 | `insufficient_permissions` | Dem Berechtigungsnachweis fehlt `signing-keys:write`, oder der Notfallmodus wurde ohne ausdrücklich erteilte `signing-keys:emergency` angefordert. |
| 404 | `not_found` | `connection_id` nennt keine SAML-Verbindung dieser Umgebung. |
| 409 | `connection_keys_not_dedicated` | `connection_id` nennt eine Verbindung, die die SP-Schlüssel der Umgebung verwendet. |
| 409 | `next_key_too_young` | Ein Algorithmuswechsel steht aus und der `next`-Schlüssel wurde vor weniger als 7 Tagen veröffentlicht, oder (Föderationsschlüssel, `immediate`) der `next`-Schlüssel wurde vor weniger als 7 Tagen veröffentlicht. |
| 409 | `conflict` | Die Umgebung hat keinen veröffentlichten `next`-Schlüssel, keinen aktiven Schlüssel des Föderations-`use`, oder der vorherige Föderationsschlüssel befindet sich noch in seiner 30-tägigen Überlappung. |
| 415 | `unsupported_media_type` | Der Content-Type ist nicht `application/json`. |
| 422 | `validation_failed` | Ein Feld fehlt oder ist ungültig; der Pointer nennt das Feld, zum Beispiel `/reason`. |
| 422 | `idempotency_key_reuse` | Der `Idempotency-Key` wurde bereits mit einem anderen Body verwendet. |
| 501 | `not_implemented` | Der Vorgang ist in dieser Bereitstellung noch nicht verfügbar. |
| 401 | `unauthenticated` | Der Berechtigungsnachweis fehlt, ist ungültig oder widerrufen. |
| 429 | `rate_limited` | Das Ratenlimit wurde überschritten; wiederholen Sie den Aufruf nach dem Zeitraum `Retry-After`. |
| 503 | `service_unavailable` | Eine Abhängigkeit ist vorübergehend nicht verfügbar; wiederholen Sie den Aufruf nach dem Zeitraum `Retry-After`. |

## Beispiel

Reguläre Rotation:

```bash
curl -X POST "https://api.eu.keenauth.com/v1/signing-keys:rotate" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"mode":"immediate"}'
```

Notfallrotation mit einem eingeschränkten Schlüssel, der `signing-keys:write` und `signing-keys:emergency` gewährt:

```bash
curl -X POST "https://api.eu.keenauth.com/v1/signing-keys:rotate" \
  -H "Authorization: Bearer $KEENAUTH_EMERGENCY_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"mode":"emergency","revoke_sessions":true,"reason":"INC-2041 key exposure"}'
```

Notfallrotation des SAML-SP-Signierschlüssels, die außerdem den veröffentlichten `next`-Schlüssel widerruft:

```bash
curl -X POST "https://api.eu.keenauth.com/v1/signing-keys:rotate" \
  -H "Authorization: Bearer $KEENAUTH_EMERGENCY_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"mode":"emergency","use":"saml_sp_signing","revoke_next":true,"reason":"INC-2042 SP key exposure"}'
```

Notfallrotation des dedizierten SAML-SP-Signierschlüssels einer Verbindung:

```bash
curl -X POST "https://api.eu.keenauth.com/v1/signing-keys:rotate" \
  -H "Authorization: Bearer $KEENAUTH_EMERGENCY_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"mode":"emergency","use":"saml_sp_signing","connection_id":"conn_01h2xcejqtf2nbrexx3vqjhp41","reason":"INC-2043 connection key exposure"}'
```
