fix(middleware): forward configured headers on SSE/WebSocket bypass (#162)

The SSE and WebSocket bypass forwarded only X-Forwarded-User. It did not
apply the configured headers. Backends that authenticate the proxy with a
shared-secret header returned 401 on WebSocket upgrades. Version 0.8.x sent
WebSocket upgrades through the normal flow, so this is a regression.

The bypass now renders the header templates through applyHeaderTemplates,
which forwardAuthorized also uses. Templates use the ID-token claims from
the session cookie. If the session has no ID token, they use the
access-token claims.

The bypass now also rejects a session that the IdP logged out through
back-channel or front-channel logout. Without this check, a logged-out
cookie can open streams with the proxy secret attached.

Add a yaegi check for the WebSocket case. Move tokenWithGroups to the
shared JWT test helpers, as FIX-41 requires.

Claude-Session: https://claude.ai/code/session_01G1d1n1BrHHHw8dBUkbiBPC
This commit is contained in:
2026-09-28 15:24:33 +01:00
parent 45e99551f9
commit c9844d0ff2
6 changed files with 468 additions and 93 deletions
+4 -2
View File
@@ -304,9 +304,11 @@ WebSocket upgrade. The middleware handles this automatically:
- They are **not** unauthenticated — a valid encrypted session cookie is
required, otherwise the request is rejected. The session must already exist
(i.e. the user logged in via a normal HTTP page first).
- `X-Forwarded-User` is forwarded from the session.
- `X-Forwarded-User` and the configured `headers` are forwarded from the
session. Header templates render from the claims in the session cookie.
- Validation is cookie-only (no JWK fetch), so streaming keeps working during
brief IdP outages.
brief IdP outages. Back-channel and front-channel logout still apply: a
session that the IdP logged out is rejected.
No configuration needed — this is implicit behavior.