Files
public/docs/sso-and-identity.md
T
thesabear 41a6f569b4 docs: rework security/hardening batch with diagrams and callouts
Mermaid diagrams up front, GFM alert callouts for key decisions and
gotchas, tables instead of bullet walls - replaces plain prose with
the visual template established for security-monitoring.md.
2026-08-21 23:17:10 +03:00

2.5 KiB

🪪 SSO & Identity

Note

Every app that needs single sign-on registers against the identity provider once per reverse-proxy zone it's exposed on — and a real platform limitation shapes how superuser accounts authenticate.

Login flow — same shape, every app

sequenceDiagram
    participant U as User
    participant App as App (browser-facing zone)
    participant IdP as Identity Provider (internal zone)

    U->>App: Opens app
    App->>U: Redirect to identity provider
    U->>IdP: OAuth authorize/token exchange
    Note over IdP: Always happens on the internal zone,<br/>even though the app itself lives<br/>on the browser-facing zone
    IdP->>U: Success
    U->>App: Lands back on the app

Every app-specific setting beyond this shape (token lifetime, scopes, flow type) is deliberately not generalized across apps — each app's own OIDC documentation gets read fresh rather than copying another app's provider config, since the details genuinely differ per vendor.

Registration pattern Provider + application pair per zone (up to 2 per app)
Native OIDC/SAML apps ~12 apps, where the upstream supports it directly
Everything else Proxy-based forward-auth

A real limitation, documented rather than hidden

Warning

LDAP-based login through the identity provider's own outpost isn't viable for the primary superuser account — the outpost hides superuser accounts from LDAP directory search, so any app requiring a search-then-bind flow can never authenticate that account through LDAP. The two workarounds — a second non-admin account, or demoting the primary account from superuser — were both rejected as worse than the problem. Header-based forward-auth is used instead for apps in that situation.

Git access: least privilege, not the admin account

flowchart LR
    CI["CI / Automation"] -->|scoped write| Bot["Dedicated bot account<br/>non-admin"]
    Bot --> Repo["Git server"]
    Other["Other hosts"] -->|read-only| Deploy["Deploy keys<br/>per host"]
    Deploy --> Repo

CI and automation pushes run through a dedicated, non-admin bot account with scoped write access — never through an administrator identity. Hosts that only need to read get separate read-only deploy keys instead of any shared credential. A compromised automation credential is never an admin credential.


Related stacks: stacks/identity-and-security/authentik/, stacks/platform/gitea/