OIDC auth flow, Kratos + Hydra, client registry (12 apps), session management, identity schemas, self-service flows, Vault integration.
5.7 KiB
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:
- Registers the client with Hydra
- Creates a K8s Secret with
CLIENT_IDandCLIENT_SECRET - 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:
- Requests new credentials from OpenBao's database engine
- Creates/updates the K8s Secret
- 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:
# 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. ✨