Authentication
ScaiDNS supports two authentication methods: JWT tokens issued by ScaiKey for interactive users, and API keys for machine clients. Every API request uses one or the other.
Use API keys for servers, CI, and automation. Use JWTs when a human is in the loop.
API keys#
API keys are the simplest option and recommended for any non-interactive caller.
Create a key#
From the admin UI: API Keys → Create. A key needs:
- Name. A label shown in listings and audit logs. Pick something specific.
- Permission source. A user or a group. The key inherits permissions from whichever you pick. This is the mechanism that gives the key any access at all.
- Optional rate limit. Requests per minute. Omit for unlimited (subject to platform limits).
- Optional IP whitelist. CIDR blocks. Requests from outside are rejected with
403. - Optional expiry. Timestamp after which the key is refused. Omit for no expiry.
Creation returns the full secret exactly once:
1 2 3 4 5 6 7 8 | |
Store key in a secret manager immediately. ScaiDNS does not store it in plaintext — you cannot retrieve it later. If lost, regenerate via POST /api/v1/api-keys/{key_id}/regenerate (invalidates the old secret).
Use a key#
Send the key in the X-API-Key header:
1 2 | |
1 2 3 4 5 6 | |
1 2 3 | |
Revoke vs delete#
- Revoke (
POST /api/v1/api-keys/{id}/revoke) disables the key. You can re-activate it later. Use this when the key might come back. - Delete (
DELETE /api/v1/api-keys/{id}) removes the key permanently. Use this when it's compromised or permanently retired.
JWT tokens#
Human users authenticate through ScaiKey's OAuth 2.0 authorization code flow with PKCE. ScaiDNS itself is the OAuth client, the frontend handles the browser redirect.
The three relevant endpoints:
| Endpoint | Purpose |
|---|---|
GET /api/v1/auth/config |
OAuth configuration — authorization and token endpoints, client ID, scopes |
POST /api/v1/auth/token |
Exchange an authorization code for access + refresh tokens |
POST /api/v1/auth/refresh |
Exchange a refresh token for a new access token |
Full flow#
-
Fetch config. Call
GET /api/v1/auth/configto discover the authorization endpoint, client ID, and scopes. -
Generate PKCE pair. Generate a
code_verifier(random string) and derivecode_challenge = base64url(sha256(code_verifier)). -
Redirect to ScaiKey. Send the user to
{authorization_endpoint}?response_type=code&client_id=...&redirect_uri=...&scope=...&state=...&code_challenge=...&code_challenge_method=S256. -
Receive callback. ScaiKey redirects back to your
redirect_uriwith?code=...&state=.... Verifystatematches what you sent. -
Exchange for tokens.
POST /api/v1/auth/tokenwith the code and verifier:bash1 2 3 4 5 6 7
curl -X POST https://scaidns.scailabs.ai/api/v1/auth/token \ -H "Content-Type: application/json" \ -d '{ "code": "authcode_from_callback", "code_verifier": "your_pkce_verifier", "redirect_uri": "https://your-app.example.com/oauth/callback" }'Response:
json1 2 3 4 5 6 7
{ "access_token": "eyJhbGc...", "refresh_token": "eyJhbGc...", "token_type": "Bearer", "expires_in": 3600, "id_token": "eyJhbGc..." } -
Use the access token. Send
Authorization: Bearer <access_token>on every request. -
Refresh when expired. When the access token expires,
POST /api/v1/auth/refreshwith the refresh token. You get a fresh access token.
If you are building a first-party frontend, the reference implementation in the ScaiDNS admin UI demonstrates the full flow — look at authStore.ts.
Using a JWT in requests#
1 2 | |
1 2 3 4 | |
1 2 3 | |
Scope and tenant#
Both authentication methods resolve to a tenant context. Every API request operates within a tenant:
- API keys are bound to a tenant at creation. The tenant of the key's owning user (or group's tenant) is used.
- JWT tokens carry tenant info in their claims. ScaiDNS resolves this to the internal tenant UUID on each request.
You cannot make cross-tenant calls with a non-admin key or token. Platform admins can see and mutate across tenants; see Permissions and Access.
Errors#
| Status | Meaning | Action |
|---|---|---|
401 Unauthorized |
No credentials, invalid JWT, or invalid API key | Check the header is set and the key/token hasn't expired |
403 Forbidden |
Authenticated, but the caller lacks permission | Check role assignments, domain access grants, or IP whitelist |
429 Too Many Requests |
Rate limit exceeded | Back off; inspect key's rate limit config |
Which should I use?#
| Situation | Use |
|---|---|
| A CI job mutating DNS | API key scoped to a service user or group |
| A Terraform provider | API key |
| A first-party frontend with human users | JWT via OAuth |
| A CLI on an operator's laptop | Either — API key for simplicity, JWT if audit needs to show the individual human |
| A one-off admin script | JWT if interactive (they log in once), API key if scheduled |
What's next#
- Your First Zone — full walkthrough from zero to signed zone.
- API Keys reference — every endpoint for managing keys.
- Permissions and Access — how authorization resolves.