Skip to content

v2.4.7

Choose a tag to compare

@github-actions github-actions released this 24 May 13:15

v2.4.7 — Bug fix: OIDC redirect_uri http:// behind proxies that only send X-Forwarded-Proto

Fixes #28 reported by @hbjydev (Kanidm + cloudflared).

What broke

OIDC sign-in failed at the IdP with a redirect_uri mismatch error for users behind reverse proxies that send X-Forwarded-Proto: https but do not send X-Forwarded-Host (cloudflared, many nginx configs, some Caddy setups). The plugin built redirect_uri=http://... even though the browser-facing origin was HTTPS, and the IdP correctly rejected per the OAuth 2.0 spec's exact-match requirement.

Why

BuildRedirectUri required both X-Forwarded-Proto AND X-Forwarded-Host to be present before honouring either. When only Proto came through, the combined check failed and scheme fell back to Request.Scheme — which is "http" because TLS terminates upstream in containerised deployments.

Fix

Each forwarded header is now evaluated independently:

  • X-Forwarded-Proto is honoured for scheme regardless of X-Forwarded-Host's presence
  • X-Forwarded-Host is honoured for host regardless of X-Forwarded-Proto's presence
  • Either header's absence falls through to the direct request value

The proxyTrusted gate (peer must be in TrustedProxyCidrs) is unchanged for both header checks — attackers connecting directly cannot inject either. The SEC-H1 boundary is intact.

Implementation notes

  • URL-construction logic extracted to a pure static helper Services/OidcRedirectUriBuilder.cs so it's testable without HttpContext mocking.
  • 5 new regression tests in OidcRedirectUriBuilderTests.cs:
    1. No proxy headers → direct scheme/host (baseline)
    2. Proto from trusted proxy → https propagates (the #28 fix)
    3. Proto from untrusted peer → ignored (security — Proto gate)
    4. Host from untrusted peer → ignored (security — redirect_uri-poisoning regression test)
    5. Both headers from trusted proxy → both honoured (Traefik-style positive)
  • Tests 3 and 4 are the load-bearing security ones — if a future refactor weakens the proxyTrusted gate, they fire.
  • Verified Google OIDC sign-in still works after the refactor.

Test suite

155/155 pass (was 150, +5 new in OidcRedirectUriBuilderTests). Clean build with TreatWarningsAsErrors=true.

Verify the release

cosign verify-blob \
  --certificate Jellyfin.Plugin.TwoFactorAuthv2.4.7.0.zip.pem \
  --signature Jellyfin.Plugin.TwoFactorAuthv2.4.7.0.zip.sig \
  --certificate-identity-regexp 'https://github.com/ZL154/JellyfinSecurity/.+' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  Jellyfin.Plugin.TwoFactorAuthv2.4.7.0.zip

SLSA build provenance: Jellyfin.Plugin.TwoFactorAuthv2.4.7.0.zip.intoto.jsonl — verify with gh attestation verify --owner ZL154 Jellyfin.Plugin.TwoFactorAuthv2.4.7.0.zip.