Skip to content

v2.0.0 — Jellyfin Security

Choose a tag to compare

@ZL154 ZL154 released this 20 Apr 17:21

Plugin rename from Two-Factor Authentication to Jellyfin Security. GUID unchanged — upgrades in place.

🆕 New features

  • OIDC / SSO sign-in — Google, Microsoft/Entra, Apple, Authelia, Authentik, Keycloak, PocketID, Cloudflare Access, or any OIDC-compliant IdP. PKCE S256, id_token signature + issuer + audience + nonce validation, optional AMR-based IdP-MFA enforcement, optional group allowlist.
  • Brute-force IP banning (Fail2Ban-style) — configurable threshold/window/duration, persisted across restarts, LAN/trusted-proxy/exempt CIDRs always bypass. Admin IP Bans tab lists/unbans + manual ban.
  • Impossible-travel detection — notifies when consecutive sign-ins exceed commercial-jet speed. Uses MaxMind GeoLite2-City for lat/lon.
  • Per-user IP allowlist — pin high-value accounts to specific CIDRs. Self-service in Setup.
  • Login-page provider buttons — each configured SSO provider appears below the normal form.
  • Linked Sign-In Methods card in user Setup for self-service unlink.
  • Pill-style admin tab bar with new Sign-in Methods and IP Bans tabs.

🔒 Security hardening

  • X-Forwarded-Host / Proto only honoured when peer matches TrustedProxyCidrs (prevents redirect_uri poisoning).
  • Rate limit on /Oidc/Login (20 per 5 min per IP).
  • Bridge HTML uses JsonSerializer.Serialize for JS-context injection + strict CSP + Cache-Control: no-store.
  • returnUrl validated to same-origin relative paths.
  • New /TwoFactorAuth/MyStatus (auth-only) so the Setup page shows correct TOTP state without admin permission.

🐛 Bug fixes

  • TOTP replay cache cleared on new-secret generation — fixed "Invalid code" false-positive when Begin Setup ran twice.
  • Setup page no longer silently shows "NOT SET UP" for non-admin users.
  • Default-auth provider delegation now uses IRequiresResolvedUser correctly (Jellyfin 10.11's DefaultAuthenticationProvider throws NotImplementedException on the plain Authenticate overload).
  • Provider no longer throws the 2FA challenge as an AuthenticationException — Jellyfin swallowed the payload. TwoFactorEnforcementMiddleware rewrites the 200 auth response with the challenge body, as intended.

📦 Installation

Adds JSON: https://raw.githubusercontent.com/ZL154/JellyfinSecurity/main/manifest.json in Dashboard → Plugins → Repositories, then install Jellyfin Security from the catalog.

SHA / MD5: `ACD2EC0221D308D773D3755951E1DDA3`

See README for full walkthrough (Google, Microsoft, Authelia, etc.), per-provider options, IP ban admin, and impossible-travel setup.