Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Console session and revocations

A local account whose authorities name an admin role signs in to the admin console with a username and password; the server gives it back a session token that it signs itself.

[auth.methods]
local = { enabled = true, password = true }

[[users]]
username = "eric"
password_hash = "$argon2id$..."
authorities = ["admins"]

[[admin.roles]]
name = "admins"
permissions = ["overview", "sessions", "kick", "bans", "unban", "config", "logs", "audit", "revoke", "grant"]

[admin.ban]
max_failures = 5

[admin.session]
key_file = "/secrets/admin-session.key"   # at least 32 bytes, the same on every instance
ttl_secs = 3600
max_age_secs = 43200

Sign-in counts its failures in [admin.ban], which it requires (Bans), and goes through the password hashing queue (Password hashing).

Signing in

RequestResponse
POST /admin/login {"username": "...", "password": "..."}token, to send as Bearer; username, expires_at, expires_in, auth_time, roles, permissions
GET /admin/login{"password": true} when the door signs in accounts
POST /admin/session/renew (session token)a new token, as long as max_age_secs since sign-in has not passed
GET /admin/me (any token)name, method, permissions, admin roles, expires_at, expires_in, auth_time

The token carries only the account: each request re-reads the account in effect ([[users]] or users_file) and recomputes its permissions. A reload of users_file that removes a role, changes the password or removes the account applies to the next request.

The session key

The key that signs tokens is the same on every instance: key_file, or under Kubernetes secret_name (Secrets). Without either, the key is drawn at startup: sessions live with the process, on this instance only. All the keys: Reference [admin.session].

Revoking, signing out

RequestEffect
POST /admin/revocations {"username": "eric"} (permission revoke)every session token of the account issued until then is refused, on all its tabs and devices; a new sign-in goes through. The response says lift: held (the shared state holds the revocation) or local_only (this instance only)
POST /admin/logoutthe same for the caller’s account; under a provider JWT or the static token, nothing is revoked (204) and the console forgets the token
GET /admin/revocationsthe revocations in effect; each one disappears max_age_secs after its issued_before

Streams opened under a revoked token (/admin/events, log follows) are closed.

Sharing revocations

[admin.session]
persist_file = "/var/lib/craft-file-gate/admin-revocations.json"  # a file of their own
# or, on Kubernetes:
# backend = "configmap"                                  # the chart sets it with the shared Secret
# revocation_configmap_name = "craft-file-gate-access"
reread_interval_secs = 5

All the keys: Reference [admin.session].

A shared key goes with shared revocations, and with synchronized clocks (NTP): a revocation is dated, and an instance whose clock runs ahead or behind applies it with that offset.

In the console

  • Username and password when the door signs in accounts; “Sign in with a token” takes the static token or a provider JWT, and is the only form otherwise.
  • The token lives in the page: reloading, opening a tab or closing the browser asks for sign-in again. The browser keeps only the theme and the table views.
  • The session is renewed as long as the page is open, up to max_age_secs after sign-in; a closed tab lets it end at ttl_secs. The header shows the account, its admin roles and the token’s end.
  • Logout calls POST /admin/logout: one session signs out every tab and device of the account.