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.
This commit is contained in:
thesabear committed 2026-08-22 19:30:52 +03:00
1 parent e2765ba749
commit e9af5dde32
2 files changed
+11 -27

No files matched your search

+10 -26
View File
@@ -3,36 +3,20 @@
> [!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`](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`](dns-naming.md) only works if the identity provider itself lives inside that same trust boundary.
| | |
|---|---|
| **Software** | Authentik, self-hosted |
| **Pattern** | Provider + application pair registered once per reverse-proxy zone an app is exposed on |
| **Native OIDC/SAML apps** | ~12 apps, where the upstream software supports it directly |
| **Everything else** | Proxy-based forward-auth — SSO without the app needing to implement OIDC itself |
## Dual-zone registration
## Why proxy-based forward-auth, not just native OIDC everywhere
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`](dns-naming.md), driven by actual need rather than registering every app on both zones by default.
Most self-hosted apps don't implement OIDC or SAML themselves — a media manager or a bookmarking tool typically wasn't built with enterprise SSO in mind. Requiring native OIDC support fleet-wide would have meant leaving most apps without SSO at all. Authentik's proxy-provider forward-auth pattern sits in front of any app regardless of whether it understands OIDC, checking authentication at the reverse-proxy layer before a request ever reaches the app itself. The ~12 apps that *do* support native OIDC still use it — it's a better experience where available (no separate login redirect through the proxy) — but forward-auth is what makes SSO actually fleet-wide rather than limited to whichever apps happen to support it.
## OIDC login: the redirect crosses zones, every time
## Login flow — same shape, every app
For an app using native OIDC, the login always follows the same path:
```mermaid
sequenceDiagram
participant U as User
participant App as App (browser-facing zone)
participant IdP as Authentik (internal zone)
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.
U->>App: Opens app
App->>U: Redirect to Authentik
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
```
This split matters more than it looks: the browser-facing zone enforces mutual TLS (see [`docs/dns-naming.md`](dns-naming.md)) and the app itself might live there, but the actual authentication handshake always happens against Authentik's internal-zone address. Getting this backwards — pointing the OIDC discovery/authority setting at the wrong zone — is a real, easy mistake when onboarding a new app, since the app's own login page is on the *other* zone and it's natural to assume the auth endpoint matches.
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 and copying blind is how subtle auth bugs get introduced.
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`](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
@@ -44,7 +28,7 @@ flowchart LR
Deploy --> Repo
```
This is a smaller decision than the SSO model above, but the same principle: automation should never run with more privilege than it needs. CI and orchestration pushes (the flows described in [`docs/orchestration.md`](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."
Automation should never run with more privilege than it needs. CI and orchestration pushes (the flows described in [`docs/orchestration.md`](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`](dns-naming.md), [`docs/orchestration.md`](orchestration.md), [`docs/secrets-and-pki.md`](secrets-and-pki.md) · Stacks: [`stacks/identity-and-security/authentik/`](../stacks/identity-and-security/authentik/), [`stacks/platform/gitea/`](../stacks/platform/gitea/)