Warn when proxy role gating falls back to the default admin role

Configuring PROXY_AUTH_ROLE_HEADER without PROXY_AUTH_ADMIN_ROLE now gates
admin access on an exact-case match against the "admin" default. That closes
the fail-open, but it also means an IdP sending "Admins", "Admin", or
"authentik Admins" grants nobody admin — and a proxy-auth-only deployment has
no local credential to fall back on. The change is recoverable by setting
PROXY_AUTH_ADMIN_ROLE and restarting, but only if the operator can tell that
is what happened.

Log a startup warning naming the header, the effective admin role, the
case-sensitivity, and both ways out. The warning is scoped to deployments
that actually configured a role header; defaulting the value with no role
header is inert and stays at info. The troubleshooting entry in
docs/PROXY_AUTH.md now leads with the exact-match rule, since that is where
a locked-out operator looks first.
This commit is contained in:
rcourtman 2026-08-12 09:43:52 +01:00
parent 11a8aa3b2f
commit 0c3f475dea
2 changed files with 13 additions and 2 deletions

View file

@ -65,7 +65,7 @@ location / {
| Issue | Check |
| :--- | :--- |
| **401 Unauthorized** | Verify `X-Proxy-Secret` matches `PROXY_AUTH_SECRET`. Check if headers are being stripped by intermediate proxies. |
| **Not Admin** | Verify `PROXY_AUTH_ROLE_HEADER` is set and contains `PROXY_AUTH_ADMIN_ROLE`. |
| **Not Admin** | Check the role header actually reaches Pulse and contains the admin role **exactly** — matching is case-sensitive and compares whole roles, so `Admins` and `authentik Admins` do not match the `admin` default. Set `PROXY_AUTH_ADMIN_ROLE` to your IdP's admin group name. Pulse logs a warning at startup when it falls back to the default. |
| **Logout Fails** | Ensure `PROXY_AUTH_LOGOUT_URL` is set to your IdP's logout endpoint. |
### Verify Headers

View file

@ -1404,7 +1404,18 @@ func load(initLogging bool) (*Config, error) {
// Documented default (docs/PROXY_AUTH.md). Leaving it empty while a
// role header is configured would disable role gating entirely.
cfg.ProxyAuthAdminRole = DefaultProxyAuthAdminRole
log.Info().Str("role", cfg.ProxyAuthAdminRole).Msg("Proxy auth admin role defaulted")
if cfg.ProxyAuthRoleHeader != "" {
// Role gating is live but the admin group was never named, so
// admin now hinges on an exact-case match against this default.
// An IdP sending "Admins" or "authentik Admins" grants nobody
// admin; say so here or the operator has nothing to go on.
log.Warn().
Str("role_header", cfg.ProxyAuthRoleHeader).
Str("admin_role", cfg.ProxyAuthAdminRole).
Msg("PROXY_AUTH_ADMIN_ROLE is not set, so proxy-auth admin access requires the role header to contain exactly \"admin\" (case-sensitive). Set PROXY_AUTH_ADMIN_ROLE to your IdP's admin group name if it differs, or unset PROXY_AUTH_ROLE_HEADER to treat every proxy-authenticated user as an admin.")
} else {
log.Info().Str("role", cfg.ProxyAuthAdminRole).Msg("Proxy auth admin role defaulted")
}
}
if logoutURL := os.Getenv("PROXY_AUTH_LOGOUT_URL"); logoutURL != "" {
cfg.ProxyAuthLogoutURL = logoutURL