Rotate signing keys

POST /v1/signing-keys:rotate · permission signing-keys:write

Runs a signing key rotation now, outside the automatic schedule.

Federation keys

use can also name one of the environment's federation keys: saml_sp_signing and saml_sp_encryption (the SAML service provider signing and encryption keys published in your SP metadata) or oidc_rp_signing (the private_key_jwt key of enterprise OIDC connections, published at /sso/jwks.json). These keys are always RSA-3072 and rotate once a year on their own: a new next key is published 30 days before it takes over, and the old key stays published for 30 days after.

For a federation key, next_kid in the response is null, removed_kids is empty and revoke_sessions is not allowed. If the environment never used SAML or private_key_jwt, there is no key to rotate and the call fails with 409 conflict.

Connection keys

A SAML connection can have its own dedicated SP keys instead of the environment's. To rotate those, add connection_id (conn_…) with use: saml_sp_signing or saml_sp_encryption. The same modes, permissions and rules apply, but only that connection's key set changes: the environment's keys and the other connections' keys stay as they are, and the connection.sp_certificate_rotation_started event is sent for that connection only. The audit record names the environment as its target and the connection in metadata.connection_id. An unknown connection, or a connection of another environment, fails with 404 not_found; a connection that uses the environment's keys fails with 409 connection_keys_not_dedicated (rotate the environment's keys without connection_id). Without connection_id the environment's key set is rotated.

Emergency mode needs, besides signing-keys:write, the signing-keys:emergency permission granted explicitly on the credential: only a restricted key or an M2M client carrying that permission can call it. A full-access secret key (idp_sk_…) gets 403 insufficient_permissions in emergency mode.

New token signing keys use the algorithm of the environment policy (get the policy). A successful token signing key rotation emits the signing_key.rotated or signing_key.revoked webhook event; every rotation writes a management audit record. This endpoint belongs to the "key and secret issuance" rate limit family. Send an Idempotency-Key: a retry after a network error then returns the first result instead of rotating twice.

Request

JSON body (unknown fields are rejected with 400 unknown_field):

Field Type Required Description
Idempotency-Key header no Recommended. 16-64 characters of A-Z a-z 0-9 _ -.
mode string yes immediate or emergency.
use string no The key to rotate. Default token_signing (access and ID token signing key). The federation keys are saml_sp_signing, saml_sp_encryption and oidc_rp_signing (see Federation keys).
revoke_sessions boolean no Emergency and token_signing only. Also revoke all sessions and refresh tokens. Default false.
revoke_next boolean no Emergency only. Also revoke the published next key. Default false.
reason string emergency: yes Emergency only. 1-512 printable ASCII characters, for example an incident number. Do not put secrets or personal data here.
connection_id string no saml_sp_signing and saml_sp_encryption only. A SAML connection (conn_…) with dedicated SP keys; its key set is rotated instead of the environment's (see Connection keys).

With mode: immediate, sending revoke_sessions: true, revoke_next: true or a reason fails with 422 (not_allowed). A connection_id with token_signing or oidc_rp_signing fails the same way.

Response

200 OK with the result of the rotation. activated_kid is the key that signs from now on and next_kid the newly published next key (null for a federation key). retired_kids are keys that stopped signing and stay published (7 days for a token signing key, 30 days for a federation key); revoked_kids are keys removed from the JWKS by an emergency rotation; removed_kids are retired keys whose 7-day window ended and that left the JWKS in the same step.

{
  "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
}

Errors

HTTP code When
400 unknown_field The body contains an unknown field.
400 malformed_request The body is not valid JSON, or the Idempotency-Key header is malformed or repeated.
403 insufficient_permissions The credential lacks signing-keys:write, or emergency mode was requested without an explicitly granted signing-keys:emergency.
404 not_found connection_id names no SAML connection of this environment.
409 connection_keys_not_dedicated connection_id names a connection that uses the environment's SP keys.
409 next_key_too_young An algorithm change is pending and the next key was published less than 7 days ago, or (federation key, immediate) the next key was published less than 7 days ago.
409 conflict The environment has no published next key, has no active key of the federation use, or the previous federation key is still in its 30-day overlap.
415 unsupported_media_type The content type is not application/json.
422 validation_failed A field is missing or invalid; the pointer names the field, for example /reason.
422 idempotency_key_reuse The Idempotency-Key was already used with a different body.
501 not_implemented The operation is not available in this deployment yet.
401 unauthenticated The credential is missing, invalid or revoked.
429 rate_limited The rate limit was exceeded; retry after the Retry-After period.
503 service_unavailable A dependency is temporarily unavailable; retry after the Retry-After period.

Example

Regular rotation:

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"}'

Emergency rotation with a restricted key that grants signing-keys:write and signing-keys:emergency:

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"}'

Emergency rotation of the SAML SP signing key, also revoking the published next key:

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"}'

Emergency rotation of the dedicated SAML SP signing key of one connection:

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"}'