Files
public/docs/sso-and-identity.md
T
thesabear e9af5dde32 Fix SSO section: correct README/doc split, remove unverified LDAP claim
README is short/sharp facts, docs/*.md is full depth/process/reasoning
- that split had collapsed into either near-duplicate text in both
files or the fact missing from the README entirely. README now states
the OIDC zone-crossing fact in one crisp sentence; the full doc has
the complete step-by-step breakdown. The LDAP superuser workaround
claim is removed from both - the source material frames it as
contingency guidance for a scenario that may never have come up, not
documented deployed behavior, so it doesn't belong in either file.
2026-08-22 19:30:52 +03:00

3.1 KiB

🪪 SSO & Identity

Note

Authentik is the identity provider for this fleet — self-hosted rather than an external IdP, for the same reason Vault is self-hosted in docs/secrets-and-pki.md: internal-only apps shouldn't need to trust a third party just to authenticate a login, and the two-zone reverse-proxy model in docs/dns-naming.md only works if the identity provider itself lives inside that same trust boundary.

Dual-zone registration

Every new app gets a Proxy Provider + Application pair registered per reverse-proxy zone it's actually exposed on — up to two registrations for the same app, one per zone from docs/dns-naming.md, driven by actual need rather than registering every app on both zones by default.

OIDC login: the redirect crosses zones, every time

For an app using native OIDC, the login always follows the same path:

  1. User opens the app on the browser-facing zone.
  2. The app redirects the browser to Authentik to do the actual OAuth authorize/token exchange.
  3. That exchange happens against Authentik's own address on the service-to-service zone — reachable from a browser for this one hop specifically, even though that zone doesn't get the mutual-TLS treatment the browser-facing zone does.
  4. On success, the browser lands back on the app, still on the browser-facing zone.

So an app's OIDC discovery/authority setting always points at the service-to-service zone, even though the app itself is normally reached on the browser-facing zone — the two zones are defined in docs/dns-naming.md. This is confirmed against one real app's actual login flow, not assumed to hold for every app without checking. Every other app-specific setting (token lifetime, scopes, flow type) doesn't generalize the same way — each app's own OIDC documentation gets read fresh rather than copying another app's provider config, since those details genuinely differ per vendor.

Git access: least privilege, not the admin account

flowchart LR
    CI["CI / Orchestration engine<br/>see docs/orchestration.md"] -->|scoped write| Bot["Dedicated bot account<br/>non-admin"]
    Bot --> Repo["Gitea"]
    Other["Other hosts"] -->|read-only| Deploy["Deploy keys<br/>per host"]
    Deploy --> Repo

Automation should never run with more privilege than it needs. CI and orchestration pushes (the flows described in docs/orchestration.md) 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. The practical payoff: if an automation credential ever leaks, the blast radius is "can push to specific repos," not "has full admin control of the Git server."


Related: docs/dns-naming.md, docs/orchestration.md, docs/secrets-and-pki.md · Stacks: stacks/identity-and-security/authentik/, stacks/platform/gitea/