v2.5.7 — bug-fix + OIDC-experience release.
Five reported bugs fixed, one deferred feature shipped, and a handful of admin-UX
improvements on top.
What's fixed
- Issue #52 (derpacco) — sessions getting permanently blocked by
RequestBlockerMiddlewareafterdocker compose down/up. The in-memory
verified-token set now persists as a SHA-256 hash sidecar at
/config/plugins/configurations/TwoFactorAuth/verified_tokens.json, so the
failsafeBlockTokendoesn't re-block every active session on restart. Hashes
only — a leaked sidecar yields no usable session tokens. - Issue #54 (cwildfoerster) — OIDC discovery rejected any URL resolving to a
private IP, blocking LAN-only / VPN-only Authentik / Authelia / Pocket ID
setups. New per-provider toggleAllowPrivateNetworks(Advanced, default off)
bypasses the v2.5.5 SSRF guard for that provider's outbound fetches only —
other providers keep the strict guard. - Issue #55 (Dasnap) — Users tab 500'd with
ArgumentException: Guid can't be emptywhen a junk lockout record withUserId = Guid.Emptyexisted
(created by some brute-force testing paths). Two layers:GetUsersskips junk
rows for resilience, andUserTwoFactorStore.MutateAsyncrefuses writes for
Guid.Emptyso new corruption stops at the boundary. - Issue #50 follow-up (#53 by @duongynhi000005-oss) — the embedded
login.htmlstill hadmaxlength="6"on the OTP input, blocking the 8-digit
email codes that v2.5.5 introduced. Fixed in three places. - Pending-pair action buttons silently dying — Approve / Deny / QR click
handlers now disable + show a spinner during the request, surface server
errors viaalert+console.error, and re-enable on failure. Previously a
4xx response left the button looking dead. - CodeQL
cs/simplifiable-boolean-expression— two== falsepatterns
simplified to!.
What's new
- Issue #48 feature (Gaarindor) — two independent admin toggles to hide
the "Sign in with Two-Factor Authentication" and "Sign in with passkey"
buttons thatinject.jsadds to Jellyfin's main login page. OIDC-only
deployments now look like OIDC-only deployments./TwoFactorAuth/Loginstill
works directly for admins / fallback. - OIDC step-up factor for users (deferred from v2.5.7 planning) — users
with only an IdP linked (no TOTP / passkey / recovery / email OTP) can now
satisfySelfServiceStepUpMode=Forcedby re-authenticating to that IdP in a
popup. State token is bound to the requesting userId; the IdP-returnedsub
is matched against the user's storedSsoLinkbefore the step-up token is
minted, so signing into a different IdP account doesn't grant step-up.
prompt=loginis sent so silent SSO confirmation isn't accepted.
Upgrade
- In-place. No schema breakage, no required config edits.
- 254/254 tests pass on .NET 9 / Jellyfin 10.11.10.
- The verified-token sidecar gets populated on first sign-in after upgrade. On
the first restart after that, the log line[2FA] Loaded N verified-token hashes from /config/plugins/configurations/TwoFactorAuth/verified_tokens.json
confirms persistence is active.
Verification
gh attestation verify Jellyfin.Plugin.TwoFactorAuthv2.5.7.0.zip --owner ZL154
cosign verify-blob --certificate Jellyfin.Plugin.TwoFactorAuthv2.5.7.0.zip.pem \
--signature Jellyfin.Plugin.TwoFactorAuthv2.5.7.0.zip.sig \
--certificate-identity-regexp "https://github.com/ZL154/JellyfinSecurity/.*" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
Jellyfin.Plugin.TwoFactorAuthv2.5.7.0.zip
Thanks to derpacco, cwildfoerster, Dasnap, Gaarindor, and
Belgarathian for the reports, and @duongynhi000005-oss for PR #53.