This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/docs/ICD/auth.md
2026-03-11 14:45:37 +00:00

4.3 KiB

Auth

Three auth modes, configured via AUTH_MODE env var. All three issue the same JWT after authentication — downstream middleware is auth-mode-agnostic.

Builtin Auth (default)

Username/password authentication with bcrypt hashing.

Register

POST /auth/register
{
  "username": "jdoe",
  "password": "...",
  "email": "jdoe@example.com",
  "display_name": "Jane Doe"
}

Gated by allow_registration policy. Returns same shape as Login. A unique handle is auto-generated from username (collision-safe with -2, -3 suffixes).

Login

POST /auth/login
{ "username": "jdoe", "password": "..." }

Response:

{
  "access_token": "eyJ...",
  "refresh_token": "opaque-string",
  "user": {
    "id": "uuid",
    "username": "jdoe",
    "email": "jdoe@example.com",
    "display_name": "Jane Doe",
    "handle": "jdoe",
    "role": "user",
    "auth_source": "builtin",
    "avatar_url": "/api/v1/profile/avatar?v=1234",
    "created_at": "...",
    "last_login": "..."
  }
}

Refresh

POST /auth/refresh
{ "refresh_token": "opaque-string" }

Returns new access_token and refresh_token. Old refresh token is invalidated (rotation).

Logout

POST /auth/logout
{ "refresh_token": "opaque-string" }

Revokes the refresh token. Returns { "message": "logged out" }.

mTLS Auth

Mutual TLS via reverse proxy headers. The proxy terminates TLS and forwards cert DN fields in headers. The backend auto-provisions users on first connection.

Configured by: AUTH_MODE=mtls + MTLS_HEADER_* env vars.

No explicit login/register endpoints. User identity is extracted from the TLS certificate on every request. password_hash is NULL for mTLS users.

Headers parsed:

  • MTLS_HEADER_CN (default: X-SSL-Client-CN) — common name → username
  • MTLS_HEADER_DN (default: X-SSL-Client-DN) — distinguished name → metadata
  • MTLS_HEADER_VERIFY (default: X-SSL-Client-Verify) — must be SUCCESS
  • MTLS_HEADER_FINGERPRINT (default: X-SSL-Client-Fingerprint) — stable identity

On first request with a valid cert, the system creates a user with auth_source=mtls and external_id=fingerprint.

OIDC Auth

OpenID Connect authorization code flow. Tested with Keycloak but compatible with any OIDC-compliant IdP.

Configured by: AUTH_MODE=oidc + OIDC_* env vars.

OIDC Login (redirect)

GET /auth/oidc/login

Redirects to the IdP authorization endpoint. Stores state + nonce in oidc_auth_state table (cleaned up after callback).

OIDC Callback

GET /auth/oidc/callback?code=...&state=...

Exchanges authorization code for tokens, validates ID token signature via JWKS, extracts claims. Auto-provisions user on first login with auth_source=oidc and external_id=sub. Returns HTML fragment that passes tokens to the frontend via URL fragment.

Claim mapping:

  • subexternal_id
  • preferred_usernameusername + handle
  • emailemail
  • namedisplay_name
  • groups → synced to internal groups with source=oidc

Split-horizon issuer: OIDC_EXTERNAL_ISSUER_URL can differ from OIDC_ISSUER_URL when the IdP's internal address (Docker/K8s service) differs from its external address.

OIDC env vars:

Var Required Description
OIDC_ISSUER_URL Yes IdP issuer URL for discovery
OIDC_EXTERNAL_ISSUER_URL No External issuer (if different from internal)
OIDC_CLIENT_ID Yes Client ID
OIDC_CLIENT_SECRET Yes Client secret
OIDC_REDIRECT_URL No Callback URL (auto-derived if not set)

Login Page Adaptation

The /login page adapts by AUTH_MODE:

Mode UI
builtin Username/password form + register link
mtls Certificate status display
oidc "Sign in with SSO" button

User Identity Fields

All auth modes produce users with:

Field Description
auth_source builtin, mtls, or oidc
external_id IdP subject (OIDC) or cert fingerprint (mTLS). NULL for builtin.
handle Unique @mention handle. Auto-generated, collision-safe.

handle is the canonical identifier for @mentions (replacing username in the resolution chain since v0.24.0).