Docs
  • 0.1.0latest

Clients and signing keys

Registering and removing clients from the console, and a company's signing keys: their states, rotation five minutes ahead, and withdrawal.

Routes are under <ADMIN_URL>/admin/<company>/api and follow the change rules in The admin console.

Clients (role clients)

  • GET clients?limit=&after= lists the company's registrations in id order, and GET clients/<id> reads one, each with its kind, authentication method, redirect URIs, scope ceiling, resources, grant types and key count; the single read also gives holders, how many users hold a grant to it. The console's own client is listed and marked.
  • POST clients registers one with {"client_id", "redirect_uris", "scope_ceiling", "resources", "auth_method", "assertion_alg", "jwks", "grant_types", "dpop_bound_access_tokens", "post_logout_redirect_uris", "backchannel_logout_uri", "reason"}. Only none (a public client, always with PKCE) and private_key_jwt (with EdDSA or ES256 and its public key) are offered, so no shared secret is ever made. admin-console is refused as client_reserved and a taken id as client_taken.
  • POST clients/<id>/remove with a reason deletes the registration and ends what it held: every user's grant to it is revoked as client_removed and every refresh family it held is revoked. The answer counts both and gives the time by which its access tokens stop working, at most five minutes on. Sending it again finishes a removal that stopped part way.

Changing a registration is not in the console yet: remove the client and register it again, which starts it with no grants.

Signing keys (role keys)

Each company signs with keys of its own, sealed in its database under the server's key-encryption key. The server makes a key for a company that has none and checks every five minutes for keys due to rotate.

GET keys lists the company's keys oldest first, each with its kid, algorithm, created_at and state:

StateMeaning
signingsigns new tokens
waitingpublished in the key set, signing from signs_from
previousstill published, for the tokens it signed
retiringno longer published
withdrawntaken out of the key set at once

No private part of a key is ever answered.

  • POST keys/rotate with a reason makes a successor now: published at once and signing five minutes later, so every service that caches the key set has it before its first token (409 successor_waiting while one already waits).
  • POST keys/<kid>/withdraw with a reason takes a key out of the key set at once, so every token it signed stops verifying, though a service that cached the key set may accept them for up to five minutes. When no other key could sign, a new one is made first and named as the replacement. A withdrawal revokes no refresh token; refresh tokens are random values held as digests, not signed.

What to do when a key may be exposed is in Incidents.