Commit Graph
5 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Opus 5 9d0f618e23 refactor(sso): compute the app logout target once in the sso lookup
The previous commit wrote the same proxy-aware logout expression into
four javascript.js.j2 templates. The rule it encodes - sign out of
oauth2-proxy first when the app is proxy-gated, else go straight to the
provider - belongs where proxy-gating is already decided.

utils/roles/applications/services/sso.py gains logout_url(url,
is_proxy_gated) next to get_sso_config, with OAUTH2_SIGN_OUT_PATH as the
path constant; the rd value is quoted exactly as Jinja's urlencode
filter does it. The sso lookup exposes it as the logout_url term: it
renders OIDC through the templar, takes is_proxy_gated from the same
resolution, and refuses a context without OIDC. Prometheus, Checkmk,
Baserow and Jitsi now render lookup('sso', application_id, 'logout_url').

Behaviour is unchanged: the resolver tests pin the rd encoding against
jinja2's do_urlencode, and the lookup tests cover a proxy-gated app, an
OIDC-native app, a disabled SSO and a missing OIDC.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 13:06:19 +02:00
kevinveenbirkenbachandClaude Opus 5 a69f169600 fix(logout): sign proxy-gated apps out of oauth2-proxy before Keycloak
Run 34421944328 Fediwall#1: Prometheus, Checkmk, Baserow and Jitsi inject
their own logout control, and it pointed straight at
OIDC.CLIENT.LOGOUT_URL. For an app behind oauth2-proxy that ends the
Keycloak session but leaves the proxy's own session cookie on the app,
so the app stays signed in.

When lookup('sso', application_id, 'is_proxy_gated') holds, the control
now goes through /oauth2/sign_out?rd=<url-encoded Keycloak logout>: the
proxy clears its cookie, then redirects to Keycloak. oauth2-proxy only
follows rd into its whitelist_domains, which carry the primary domain
and the node onion, so the redirect is allowed in clearnet and in tor
mode; the pihole spec already drives the same sign-out path. Apps
without the proxy keep the direct URL, and to_json quotes the value as a
JS string literal.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 13:03:59 +02:00
kevinveenbirkenbachandClaude Opus 5 75047ef459 refactor(logout): drop a redirect that never took effect
The injected logout built `?redirect_uri=<web_protocol>://<DOMAIN_PRIMARY>`
and appended it to the end-session endpoint. Keycloak 26.7.1
(roles/web-app-keycloak/meta/services.yml:49-50) does not accept
redirect_uri there - it takes post_logout_redirect_uri plus id_token_hint
or client_id - so the parameter was dropped on arrival. Run 32284541284
job 96178507650 shows the proof: Keycloak answered with its logout-confirm
interstitial carrying client_id=account, i.e. it resolved no client from
the request at all.

The value was wrong as well as inert. DOMAIN_PRIMARY is claimed only by
roles/svc-prx-openresty, which declares no sso block, so it is never a
registered redirect URI - the parameter would have been rejected on
clearnet too the moment it became effective. Under tor it also glued the
app's own scheme to the portal's host.

Removing rather than correcting is what keeps this safe: every way this
could break requires a redirect target to be validated, and after the diff
there is no target. The emitted request is a strict prefix of today's.

The same three lines were duplicated verbatim in four web-app roles;
they collapse to the bare endpoint the shared role already passed. The
caller graph is closed - initLogoutPatch appears exactly three times
(definition, export, call site) - so the arity change leaves no orphan.

Fixes nothing that was failing; no CI job was red because of this.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 14:23:30 +02:00
kevinveenbirkenbachandClaude Opus 4.7 79933b9f89 fix(web-app-prometheus): collapse persona + logout-icon path when oauth2 is off
Variant=1 of the matrix exercises prometheus with oauth2-proxy disabled,
where the role is direct-accessible and there is no session to terminate
or persona chain to drive. Three changes make that variant pass cleanly:

- `meta/services.yml` gates `javascript.{enabled,shared}` on
  `services.oauth2.enabled`, so the logout-icon injection is only
  shipped when oauth2 is actually gating the role.
- `templates/javascript.js.j2` drops the now-redundant outer `{% if %}`
  (the gating moved to `services.yml`) and clones styling from a
  sibling icon button so the injected logout matches the role theme
  (box, padding, border-radius, hover) without per-app guesses.
- `templates/playwright.env.j2` derives
  `PERSONA_ADMINISTRATOR_BLOCKED` from `services.oauth2.enabled`, so
  the persona helper skips in the no-oauth2 variant instead of
  failing on a missing logout control.
- `files/playwright.spec.js` wraps the admin-SSO and biber-denied
  tests in `safeSkipUnlessEnabled("oauth2")` so they collapse in
  the no-oauth2 variant without touching the unauth metricz path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 11:22:38 +02:00
kevinveenbirkenbachandClaude Opus 4.7 72fb5c79b7 feat(web-app-prometheus): inject Logout icon into upstream navbar
The Prometheus UI ships no in-app logout entry, so an oauth2-proxy-
gated operator can authenticate but never reach the universal-logout
chain from inside the app. Add a per-role `templates/javascript.js.j2`
(activated via `services.javascript.enabled=shared=true` in
`meta/services.yml`) that injects a Logout SVG button to the right of
Prometheus' existing icon group (theme toggle, settings, docs) once
the navbar has mounted. The injection is gated server-side on
`services.oauth2.enabled` because oauth2-proxy session cookies are
`HttpOnly` and unreachable from `document.cookie`. The button carries
`data-injected-logout` so the persona helpers can find it via the
shared `inAppLogout` candidates list.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 03:48:53 +02:00