Files
sbbb/docs/identity.md

152 lines
5.7 KiB
Markdown
Raw Permalink Normal View History

# 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. ✨