Guides / Service accounts
Service accounts and backend credentials.
Create a stable Project workload identity, grant exact scopes, issue expiring credential versions, and rotate without an outage.
Choose one identity per workload
Create a separate service account for each independently deployed backend, job, or operational tool. Do not share one account across unrelated systems: attribution, scope reduction, incident response, and rotation all become ambiguous. A service account belongs to exactly one Project and its credentials are rejected on every other Project path.
Grant exact scopes
| Scope | Capability |
|---|---|
project_users.read | List and inspect Project Users. |
project_users.write | Create and update Project Users, replace passwords, and remove passkeys. |
authentication.perform | Run Project User login, factor, enrollment, and authentication ceremonies. |
sessions.manage | Introspect and revoke Project User sessions. |
Scopes are independent; write does not silently imply read. A scope removal takes effect on the credential’s next request. Insufficient authority returns 403 insufficient_scope with the required scope in WWW-Authenticate.
Create and issue
- Create the service account with a unique
Idempotency-Key, a name, optional description, and a non-empty exact scope set. - Issue a named credential beneath it with a second idempotency key. Omit
expires_atfor the 90-day default; the allowed range is more than five minutes and at most 365 days. - Copy the returned
secretimmediately into a server-side secret manager. It appears only in the issuance response and exact 24-hour idempotent replays. - Send it as
Authorization: Bearer <service-credential>from the customer backend. Never place it in browser code, a URL, logs, screenshots, or support attachments.
Sandbox credentials start with ca_sk_test_; production credentials start with ca_sk_live_. Prefixes make accidental environment use visible, but the API still authorizes from persisted Project and status boundaries rather than trusting the string label.
Rotate with overlap
- Issue a replacement credential while the old version is still active.
- Deploy the replacement to every instance of the workload.
- Observe the replacement’s
last_used_at. Allow enough time for old instances, queues, and rollback windows to drain. - Revoke the old credential with its nested
DELETEoperation. Repeating that request remains a successful204.
At most two active, unexpired credentials may overlap. There is deliberately no rotate RPC: issuing and revoking separate resources preserves safe deployment ordering and makes partial failure recoverable.
Lifecycle and concurrency
Service-account reads return a strong ETag. Send it in If-Match when updating scopes or status and when deleting; a stale representation returns 412 version_conflict. Disabling or deleting the account permanently revokes all active credentials. Re-enabling the identity does not resurrect them—you must issue a new credential.
Credential metadata is safe to list and includes prefix, SHA-256 fingerprint, creator, expiry, last use, and revocation reason, never the reusable secret. History is cursor-paginated in reverse creation order. Pass next_cursor back unchanged as cursor.
Retries and failure handling
- For account and credential creation, retain the original idempotency key with the logical operation. Exact retries replay the same status, headers, body, and one-time secret for 24 hours; changed input conflicts.
- Retry connection failures and transient
5xxresponses with bounded exponential backoff and jitter. Do not invent idempotency for operations that do not publish it. - Treat
401 invalid_service_credentialas expired, revoked, disabled, malformed, or wrong-Project credential state. Fetch safe control-plane metadata instead of repeatedly retrying the secret. - Use the credential UID and fingerprint when coordinating an incident. Never transmit the secret itself.
Service credentials are not OAuth tokens
A service credential authenticates a customer-controlled workload to one ComplicatedAuth Project API. OAuth access tokens represent a Tenant Member’s delegated grant to one registered Resource Server. Neither credential is accepted as the other, and neither authorizes management-console operations.