Files
sbbb/docs/identity.md
Sienna Meridian Satterwhite 97e87c6dda docs: add identity & auth documentation — The Guest List 💋
OIDC auth flow, Kratos + Hydra, client registry (12 apps), session
management, identity schemas, self-service flows, Vault integration.
2026-03-24 11:46:28 +00:00

152 lines
5.7 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# The Guest List 💋
Every app in The Super Boujee Business Box ✨ authenticates through the same door. One login, every room. You don't re-authenticate because you walked from Docs to Drive — that's not a feature, that's just manners.
The identity layer is built on **Ory Kratos** (who you are) and **Ory Hydra** (what you're allowed to do). Lightweight Go binaries, no JVM, no XML — they fit k3s like they were born for it. We chose them over Keycloak because we wanted something that didn't need 2GB of RAM to tell you who's logged in.
---
## The Auth Flow
```
You → any app (docs.sunbeam.pt, drive.sunbeam.pt, etc.)
→ 302 redirect to auth.sunbeam.pt
→ Hydra says "who are you?"
→ Kratos login UI (password, TOTP, WebAuthn — your pick)
→ authenticate
→ Hydra issues OIDC token
→ 302 back to the app
→ app validates via mozilla-django-oidc
→ session established ✨
```
That's it. Every La Suite app uses the same `mozilla-django-oidc` library. Swapping from Keycloak (the French government default) to Hydra was transparent at the app level — same OIDC, different provider.
---
## The Players
### Ory Kratos — Identity Management
Handles the "who are you" part:
- **Registration** — create accounts (or provision them via `sunbeam auth identity create`)
- **Login** — password, TOTP, WebAuthn, lookup secrets
- **Profile** — name, email, metadata
- **Recovery** — password reset via email (through Postfix)
- **Session** — 720 hours (30 days), cookie-scoped to parent domain
The cookie-scoping is key: setting the session cookie on the parent domain means all `*.sunbeam.pt` subdomains share the session. Log in once, you're everywhere.
### Identity Schemas
Three schemas for different types of users:
| Schema | Purpose |
|--------|---------|
| `employee` | Core team (Sienna, Amber, Lonni) — full access, all apps |
| `default` | Standard users — for when the team grows |
| `external` | External collaborators — limited scope |
### Ory Hydra — OAuth2 / OIDC Provider
Handles the "what can you do" part:
- Issues OAuth2 access tokens and OIDC ID tokens
- Manages the OIDC client registry
- Token lifetimes: access/ID tokens 1h, refresh tokens 720h, auth session 720h
- OpenID Connect discovery at `auth.sunbeam.pt/.well-known/openid-configuration`
### Hydra Maester
The secret sauce for client management. Watches `HydraOAuth2Client` CRDs in Kubernetes and automatically:
1. Registers the client with Hydra
2. Creates a K8s Secret with `CLIENT_ID` and `CLIENT_SECRET`
3. Keeps them in sync if the CRD changes
No manual client registration. Declare a CRD, get a working OIDC client.
---
## The OIDC Client Registry
Every app is a registered OIDC client. Hydra Maester manages all of them:
| App | Secret Name | Redirect URI | Notes |
|-----|-------------|-------------|-------|
| Docs | oidc-docs | `docs.DOMAIN/api/v1.0/callback/` | |
| Drive | oidc-drive | `drive.DOMAIN/api/v1.0/callback/` | |
| Meet | oidc-meet | `meet.DOMAIN/api/v1.0/callback/` | |
| Messages | oidc-messages | `mail.DOMAIN/api/v1.0/callback/` | `offline_access` scope |
| People | oidc-people | `people.DOMAIN/api/v1.0/callback/` | |
| Find | oidc-find | `find.DOMAIN/oidc/callback/` | |
| Gitea | oidc-gitea | `src.DOMAIN/user/oauth2/Sunbeam/callback` | |
| Calendars | oidc-calendars | `cal.DOMAIN/api/v1.0/callback/` | |
| Projects | oidc-projects | `projects.DOMAIN/oidc-callback` | |
| Hive | oidc-hive | *(none)* | `client_credentials` grant |
| Tuwunel | oidc-tuwunel | *(matrix namespace)* | Matrix SSO |
| Grafana | grafana-oidc | *(monitoring namespace)* | auto-assign Admin role |
Messages gets `offline_access` to maintain sessions across browser restarts. Hive uses `client_credentials` because it's a service, not a human. Grafana auto-assigns Admin because if you're authenticated, you're on the team.
---
## Self-Service Flows
Users can manage their own security:
| Method | What it is |
|--------|-----------|
| **Password** | Classic email + password |
| **TOTP** | Time-based one-time passwords (Google Authenticator, etc.) |
| **WebAuthn** | Hardware security keys (YubiKey, etc.) |
| **Lookup Secrets** | Backup/recovery codes |
Recovery emails go through Postfix (same SMTP used by Messages) at `postfix.lasuite.svc:25`.
---
## Vault Integration
Secrets don't live in Git. They live in OpenBao (Vault) and sync to Kubernetes via Vault Secrets Operator.
### OIDC Client Secrets
Hydra Maester creates K8s Secrets from HydraOAuth2Client CRDs. These contain `CLIENT_ID` and `CLIENT_SECRET` that apps consume.
### Dynamic Database Credentials
Every app's database password rotates every 5 minutes via `VaultDynamicSecret`. The Vault Secrets Operator:
1. Requests new credentials from OpenBao's database engine
2. Creates/updates the K8s Secret
3. Triggers a rollout restart of the affected Deployment
### Static Secrets
Django secret keys, DKIM keys, API tokens — synced from OpenBao KV v2 with 30-second refresh via `VaultStaticSecret`.
---
## Admin Access
For when you need to manage identities directly:
```bash
# Via sunbeam CLI
sunbeam auth identity list
sunbeam auth identity create amber@sunbeam.pt --name "Amber"
sunbeam auth identity get <id>
# Via Kratos Admin API (auth-gated through proxy)
# Accessible at id.sunbeam.pt (requires Hydra /userinfo auth)
# Via Hydra Admin API (auth-gated through proxy)
# Accessible at hydra.sunbeam.pt (requires Hydra /userinfo auth)
```
Sol☀ also has Kratos admin access for identity operations within Matrix chat.
---
## The Login UI
Sunbeam-branded login, consent, and recovery pages served by `kratos-admin-ui`. This is what you see at `auth.sunbeam.pt` — the velvet rope. Custom logo, custom colors, same energy as everything else in the box. ✨