Chapter 4

API keys

How your own server talks to Cloud Auth without a person being present.

What a key is

A key inherits the permissions of the account that issued it, and is pinned to the tenant it was issued for. Unlike a person's session it cannot switch tenants, so a leaked key cannot reach across to another one. A service handling several tenants needs a key per tenant.

A key is not a person, and the difference is the point. Anything that needs an authenticator code is closed to keys, because there is nobody to ask for one. That includes issuing and revoking keys, and changing the issuer's own credentials — a leaked key must not be able to extend its own access or cover its tracks.

Using one

Put the secret in the X-API-Key header. Nothing else is needed — no Authorization header and no cookie. That header is deliberately not on the CORS allowlist, so a browser cannot send one even by mistake.

curl -X POST https://api.albos.org/auth.v1.AuthService/VerifyToken \
  -H "Content-Type: application/json" \
  -H "X-API-Key: ca_..." \
  -d '{"accessToken":"eyJhbGci..."}'

What a key can call

PurposeEndpointNotes
Check a tokenAuthService/VerifyTokenWhether an access token you were handed is still good. This is what a key is for.
Who the account isAuthService/GetCurrentUserThe account the key was issued by.
Which tenantsTenantService/ListMyTenantsThe role in each comes back as myRole.
LivenessGET /healthNo authentication. Reports whether the database is reachable.
That is the whole list. Member lists, user administration, invitations and key listings all sit behind the code requirement, so a key gets 403 rather than data. Build your integration around verifying tokens; anything that administers accounts is done by a person who has just entered a code.

Read-only, or read-write

A key is read-only unless read-write was chosen when it was issued. What a read-only key may call is an allowlist rather than a list of things it may not, so an endpoint added tomorrow is closed to it until somebody decides it is safe.

In practice the difference rarely bites, because so little is reachable by a key at all. Choose read-only unless you know why you need the other one: a key that cannot change anything is a much smaller prize.

Looking after keys

  • Keys expire. 30 days unless a longer one was asked for, and 90 at the outside. An expired key stops authenticating, so replace it before it runs out; the management screen warns from 14 days out.
  • Rotate by issuing first, revoking second. Every tenant can hold at least two keys at once, so in that order the change needs no downtime.
  • Issue a separate key per purpose, so revoking one does not take down everything.
  • If you suspect a key has leaked, revoke it from the management screen. Revocation takes effect from the next request.
  • Every issue and every revocation is recorded in the audit log.
  • How many keys can be live at once depends on the plan: two on Free, three on Light, twenty on Pro.
  • Each key has its own allowance of 600 requests a minute, separate from the per-address ceiling, so a busy integration calling from one server is not throttled alongside an attacker. Going over returns resource_exhausted.

When it does not authenticate

What happenedWhat comes back
The key is unknown, revoked or expired — or the issuing account has been disabledunauthenticated (401). Which of these it was is not distinguished.
A read-only key attempted a changepermission_denied (403). Retrying will never help.
The call needs an authenticator codepermission_denied (403), not 412 — so a client does not retry for ever.
The key's own rate limit was reachedresource_exhausted (429). Wait before retrying.

The full list of codes is in Chapter 6.