Skip to content

v2.5.21

Latest

Choose a tag to compare

@github-actions github-actions released this 04 Aug 17:30

v2.5.21

This release fixes the "signed in successfully, then thrown straight back to the login page" bug at its root, makes the plugin work when Jellyfin is served under a Base URL, and turns notifications into something you can actually authenticate and test. Drop-in from any 2.5.x — no config or data migration.

Highlights

  • No more bounce back to the login page after a successful 2FA or SSO sign-in. (Fixes #137, #98.) Two independent causes, both fixed. The client-side "2FA pending" flag that suppresses API calls mid-challenge was only ever cleared by the OIDC bridge, so completing a password + 2FA login left it armed and Jellyfin Web's entire post-login bootstrap was blocked on the next page load. Separately, the stored credential recorded connection mode Remote while only ever populating a manual address, so Jellyfin resolved the server address to undefined. This is why it reproduced externally (through a reverse proxy) but never on the LAN. Verified end-to-end through Cloudflare + a reverse proxy, including surviving a page reload.

  • The Setup page and 2FA challenge work behind a Base URL. (Fixes #144.) Every API call from /TwoFactorAuth/Setup was hard-coded to the origin root, so any server mounted under a path (https://host/jellyfin/) got a 404 on /Users/Me and the page reported "We couldn't verify your Jellyfin session". Nothing was ever wrong with the session — the page was asking the wrong origin. Both pages are now Base-URL aware.

  • User details load in the admin Users table. (Fixes #156.) The inline ▸ details panel was reading the step-up-gated full export, so on any server with step-up enabled it always returned 403 and printed "Failed to load details". It now reads a dedicated summary endpoint carrying only what the panel shows — device labels and dates — with no audit log, IPs, device ids, or email. The per-user Export button (which genuinely should be gated) now prompts for the step-up code instead of failing silently.

SSO / OIDC

  • Sign-in no longer breaks when an identity provider's signing certificate expires. (Fixes #142, #98.) Authentik's self-signed signing certificate expires after a year and doesn't auto-rotate, and the plugin was rejecting otherwise-valid tokens because of it. The token signature is still fully verified against the provider's published keys — only the certificate's expiry date is no longer treated as fatal.
  • OIDC sign-in failures now say what's wrong. Instead of one opaque "Sign-in token could not be verified", a failed sign-in now names the cause — expired certificate, signing-key mismatch, Client ID mismatch, clock drift, or an unsupported signing algorithm — with configuration guidance and without leaking any library internals. The message now also reliably surfaces on the login page on Jellyfin 10.11.

Notifications

  • ntfy authentication. (#143.) Add an access token (Authorization: Bearer …) or a username + password (Basic auth), so a topic with a write ACL no longer has to be opened up to anonymous writes to receive alerts.
  • Custom webhook headers. For receivers that authenticate with Authorization: or X-Api-Key: rather than the HMAC secret. Header names/values are validated against header-injection, and the dispatcher's own headers can't be overridden.
  • "Send test notification" tests every configured channel — ntfy, Gotify and the webhook — and reports each one's result, instead of refusing to run without a webhook URL and reporting a flat "Sent".
  • The security score credits any notification channel, so an ntfy-only or Gotify-only setup is no longer docked points for not having a webhook.

Fixes & hardening

  • The injected XMLHttpRequest wrapper now leaves synchronous requests completely untouched, so a sync-xhr Permissions-Policy violation raised by another plugin's jQuery is no longer attributed to this plugin's inject.js. (#149.) The plugin itself issues no synchronous XHR. The README documents an obsolete-feature-free Permissions-Policy header.
  • Removed an unused admin download helper whose unhandled promise rejection surfaced as an "Uncaught (in promise)" console error. (#149.)
  • Fixed a dead branch in the XHR interceptor that made the 2FA-pending flag impossible to clear over XHR.

Upgrade

Drop-in from any 2.5.x — no config or data migration. Sigstore-signed + SLSA build-provenance attested. All 855 translation keys complete across 8 languages. 387/387 tests pass on .NET 9 / Jellyfin 10.11.x.