Authentication & API keys
ScaiLog authenticates every request with a built-in API key — no external service required. This is deliberate: ScaiLog is the foundational logger every other platform service logs into, so a runtime dependency on an auth service would create an unbootstrappable cycle (design invariant P1). An optional OIDC/SSO plugin sits on top for human operators and the admin panel, but API keys always remain the base mechanism and the system stays fully usable without OIDC.
API keys are the base mechanism#
Keys are bearer tokens of the form slk_<role-hint>_<secret>. The server stores
only their SHA-256 hash — the plaintext is shown once at creation and is never
recoverable. A key is bound to one tenant (or * for all tenants) and can be
narrowed to specific services. Keys optionally carry an expiry, a per-minute rate
limit, and an IP allowlist.
Send a key as a bearer token on every request:
1 | |
Roles and capabilities#
Each key has a role; the role grants a set of capabilities. Endpoints require a capability, so you scope access by choosing the narrowest role that works.
| Role | Capabilities | Typical use |
|---|---|---|
log_writer |
ingest |
An agent shipping batches, or a service ingesting directly. |
log_reader |
query |
Read-only log search and tail. |
log_reader_plus |
query, decrypt_one |
A reader that can also decrypt a single PI field on demand. |
log_admin |
query, decrypt_one, admin |
Manage keys, policies, and sites within scope. |
dpo |
ingest, query, decrypt_one, admin, dpo |
Full operator/data-protection role; runs DSAR and erasure. |
Two containment rules keep an admin from escalating: a tenant-scoped or
service-scoped admin can only mint keys within its own scope, and only a
dpo key may create another key that carries the dpo capability.
The bootstrap key#
The first key is minted automatically when you initialize an empty server. It is
a dpo key scoped to all tenants (*) — the full-access operator key you use to
create every narrower key.
1 2 | |
If keys already exist, --init mints nothing. Treat the bootstrap key as a
break-glass secret: use it to create per-service and per-operator keys, then keep
it somewhere safe rather than embedding it in services. (The admin panel stores
credentials in sessionStorage, never localStorage, precisely so a
full-access bootstrap key does not persist across restarts.)
Minting keys#
From the CLI#
1 2 3 | |
keys create prints the new key id and the plaintext key once.
Over HTTP#
POST /v1/keys requires an admin-capable caller. The response returns the
plaintext under key, shown once:
1 2 3 4 5 | |
GET /v1/keys lists keys (a tenant-scoped admin sees only its own tenant's
keys), and DELETE /v1/keys/{key_id} revokes one.
Optional: OIDC / SSO for humans#
For human operators — the CLI and the admin panel — ScaiLog can additionally
accept an OIDC ID token issued by ScaiKey or any standards-compliant provider.
This is an optional plugin that must degrade to built-in keys: if the plugin
isn't configured or the scaikey-sdk extra isn't installed, only API keys are
accepted (design invariant P1). OIDC never touches the ingest hot path — agents
authenticate with built-in API keys — so the identity provider being slow or down
cannot block log ingestion.
Server side#
Install the extra and configure the provider:
1 | |
The server enables the plugin when both SCAILOG_OIDC_BASE_URL and
SCAILOG_OIDC_CLIENT_ID are set (SCAILOG_OIDC_CLIENT_SECRET and
SCAILOG_OIDC_DEFAULT_TENANT are optional). It validates the ID token's
signature and claims (JWKS-backed) and maps the scailog_role claim to a ScaiLog
role; a token with no recognized role falls back to log_reader. Tenant mapping
fails closed: a token with no tenant claim is rejected unless
SCAILOG_OIDC_DEFAULT_TENANT names the single tenant such logins map into — a
tokenless-tenant login is never granted the * all-tenant scope.
CLI side#
The CLI logs in with the OAuth 2.0 device flow (RFC 8628) against the provider's discovery document — it carries no ScaiKey dependency:
1 2 3 | |
The device flow prints a URL and a user code to enter in a browser. On success
the CLI stores the session (~/.config/scailog/credentials.json, mode 0600),
separate from any static API key, and auto-refreshes the ID token. Token
precedence when the CLI makes a request: an explicit SCAILOG_API_KEY
environment variable wins, then a valid OIDC ID token, then the configured API
key.
Admin panel#
The admin panel offers the same two ways in: paste an API key, or "Sign in with
SSO" (Authorization Code + PKCE) when the panel is built with VITE_OIDC_ISSUER
and VITE_OIDC_CLIENT_ID. Either way it sends a bearer token and calls
GET /v1/whoami, then hides features by capability. A ScaiKey "super-admin" maps
to the dpo role via the scailog_role claim.