docs(auth): address authentication guide review

This commit is contained in:
2026-08-18 03:33:00 +02:00
parent f4f38717e1
commit 91925d64bf
12 changed files with 406 additions and 142 deletions
+52 -6
View File
@@ -14,8 +14,15 @@ read from the mounted secret bundle and are never placed in YAML, command argume
diagnostics, or browser storage.
Local users have Argon2id password hashes, stable IDs, enabled state, roles, and `authRevision`.
The stable roles are `user` and `admin`; `admin` inherits `user` and adds installation, session,
Pi, workspace, secret-management, and diagnostic permissions.
The production role expansion from `backend/src/auth/config.ts` is exact:
| Role | Permissions |
|---|---|
| `user` | `session.use` |
| `admin` | `session.use`, `session.read_all`, `session.manage_all`, `settings.manage`, `workspace.manage`, `workspace.secrets.manage`, `pi.manage`, `auth.diagnostics.read` |
`admin` therefore includes the ordinary `session.use` permission. No other role or permission
label is part of the production catalog.
OIDC is provider-neutral at the browser protocol boundary. Authorization Code + PKCE, issuer,
signature, audience, expiry, state, and nonce are validated before a principal is created.
@@ -24,15 +31,54 @@ Authentik is the first certified group-catalog adapter, not a special browser lo
## Group authorization
OIDC must return a direct, non-empty `groups` claim whose value is a JSON array of strings.
Missing, malformed, indirect, or overage-style claims fail closed with
`oidc_groups_claim_invalid`. Exact configured external group names map to Thoth roles and then to
permissions. A user with no mapped group is authenticated but receives no role and gets `403` from
protected routes. Unmapped upstream groups are ignored silently, without an error or warning.
Missing, malformed, indirect, or overage-style claims fail closed. The browser callback returns
HTTP 401 with the generic code `oidc_callback_failed`; it does not expose the internal reason.
Authentication diagnostics and interactive device-flow validation use
`oidc_groups_claim_invalid` for invalid group-claim/identity results. Exact configured external
group names map to Thoth roles and then to permissions. A user with no mapped group is
authenticated but receives no role and gets `403` from protected routes. Unmapped upstream groups
are ignored silently, without an error or warning.
Every configured mapping is checked by the configured group-catalog adapter. Authentik checks the
exact group name and reports `oidc_mapped_group_missing` when it cannot find it. The dedicated
Authentik API service account has group-view-only privilege; it is separate from the OIDC client.
## Diagnostics and ordering
The closed production diagnostic-code union is:
```text
auth_ready
auth_config_incomplete
auth_config_invalid
auth_session_store_invalid
local_user_registry_invalid
local_admin_missing
oidc_secret_missing
oidc_discovery_unreachable
oidc_issuer_mismatch
oidc_jwks_unreachable
oidc_group_catalog_unreachable
oidc_group_catalog_unauthorized
oidc_mapped_group_missing
oidc_mapped_group_ambiguous
oidc_groups_claim_invalid
oidc_device_flow_unavailable
```
Workspace Validate performs static authentication validation without provider connectivity.
`tht auth check` performs live, non-interactive diagnosis: static safety plus OIDC discovery,
issuer/JWKS, group-catalog authentication, and exact configured-group existence. Adding
`--interactive` runs that same live diagnosis and then validates a device-flow identity when the
provider supports Device Authorization. Workspace Test is the aggregate live workspace and
authentication validation.
The ordered `tht doctor` report is exactly: `descriptor`, `files`, `docker`, `compose`,
`configuration`, `authentication`, `services`, `core-http`, `frontend-http`,
`workspace-registry`, `workflow`, `pi`. Its `authentication` entry is the live non-interactive
diagnosis against the healthy running core; later checks may be skipped when an earlier
prerequisite fails.
## Browser sessions
The browser receives only an opaque `HttpOnly`, `SameSite=Lax` cookie named `thothii_session`.