Authentication
ScaiVault accepts bearer tokens issued by ScaiKey. Every request except /v1/health and /v1/health/ready requires one. There are three token flavors, for three different use cases.
Token types#
| Type | Use when | Shape | Lifetime |
|---|---|---|---|
| Personal access token | A human scripts against the API | skt_... |
Configurable (default 90d) |
| Client credentials JWT | A service calls the API | JWT starting with eyJ |
1h, refresh via client-credentials flow |
| User session JWT | A user is signed into a ScaiLabs app | JWT starting with eyJ |
1h, refresh via OAuth refresh token |
All three go in the Authorization: Bearer ... header. ScaiVault validates the signature against ScaiKey's public keys (JWKS cached locally).
Use client-credentials tokens for server-to-server traffic. Personal access tokens are fine for scripting and CI, but they belong to a human — if that human leaves, their tokens should be revoked. Services should authenticate as services.
Getting a client-credentials token#
Create a service account in ScaiKey, assign it the scopes it needs, and get back a client_id and client_secret. Then exchange them for an access token:
1 2 3 4 5 6 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
1 2 3 4 5 6 7 8 9 10 11 | |
Tokens last one hour. Your client should cache and re-request on expiry; all official SDKs do this automatically.
Scopes#
A token can only do what its scopes allow. The set of scopes is intersected with the caller's policies — both must permit the action.
| Scope | What it lets you do |
|---|---|
secrets:read |
Read secret values |
secrets:write |
Create and update secrets |
secrets:delete |
Delete secrets |
secrets:list |
List secrets and metadata |
secrets:rotate |
Trigger rotations |
policies:read |
View policies |
policies:write |
Create, update, delete policies |
audit:read |
Query audit logs |
audit:export |
Export audit data |
pki:issue |
Issue and sign certificates |
pki:admin |
Manage PKI roles, CAs, revocation |
dynamic:read |
View dynamic engines, roles, leases |
dynamic:generate |
Generate dynamic credentials |
dynamic:manage |
Configure engines and roles |
dynamic:revoke |
Revoke leases |
subscriptions:read / subscriptions:write |
Consume events |
federation:read / federation:write |
Manage federated backends |
identity:read / identity:admin |
Read identity cache / trigger sync |
admin |
All of the above |
Ask for the narrowest set of scopes that does the job. A token that can only read from one path is dramatically less dangerous than an admin token.
Using the token#
Every request:
1 2 | |
If you omit the header, you get 401 authentication_required. If the token is malformed or expired, 401 token_expired. If the scope is insufficient, 403 access_denied.
Request headers#
| Header | Required | Description |
|---|---|---|
Authorization |
Yes | Bearer <token> |
Content-Type |
On PUT/POST/PATCH |
application/json |
X-Request-ID |
No | Client-supplied ID for end-to-end tracing |
X-Partner-ID |
No | Explicit partner context (partner admins) |
X-Tenant-ID |
No | Explicit tenant context (partner admins acting cross-tenant) |
Tenant context#
The token's tenant_id claim determines which tenant you act as. Most API paths (/v1/secrets/*, /v1/policies/*) are tenant-scoped — you only see and touch your own tenant's data.
Three exceptions:
-
Partner admins can use the
/v1/t/{tenant_id}/prefix to act as a specific tenant under their partner:bash1GET /v1/t/tnt_acme_dev/secrets/app/db/password -
Partner-scoped secrets live under
/v1/partner/secrets/*and are visible to every tenant under the partner. Useful for things like "shared trust anchors" or "partner-wide default configs". -
System endpoints like
/v1/identity/partnershave their own scope checks.
See Multi-tenancy for the full model.
Tokens and rotation#
Service-account client secrets should be rotated periodically. The recommended pattern: store the secret in ScaiVault (yes, really), rotate it on a schedule, and let your service fetch it at startup.
Chicken-and-egg: the service needs some credential to talk to ScaiVault. That credential — the bootstrap token — is usually injected by your deployment platform (Kubernetes service account token, AWS IAM role, Nomad Workload Identity, GCP Workload Identity) and exchanged for a ScaiKey JWT on boot.
What's next#
- Your First Integration — a service reading secrets end-to-end.
- Multi-tenancy — tenant and partner scoping.
- Authentication Reference — endpoint details.