From 8507a772153fd800e8dc7916c5796032fecac48c Mon Sep 17 00:00:00 2001 From: Kenny Bondelie Date: Wed, 9 Sep 2026 20:49:42 -0700 Subject: [PATCH] fix: use modern Jellyfin authorization --- app/services/jellyfin.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/app/services/jellyfin.py b/app/services/jellyfin.py index c693bf4..221eb4d 100644 --- a/app/services/jellyfin.py +++ b/app/services/jellyfin.py @@ -1,9 +1,20 @@ import httpx from app.config import settings -_headers = { - "X-MediaBrowser-Token": settings.jellyfin_api_key, -} + +def _authorization_header(token: str | None = None) -> str: + values = [ + 'Client="Movie Night"', + 'Device="Web"', + 'DeviceId="movie-night-app"', + 'Version="1.0.0"', + ] + if token: + values.insert(0, f'Token="{token}"') + return f"MediaBrowser {', '.join(values)}" + + +_headers = {"Authorization": _authorization_header(settings.jellyfin_api_key)} _client: httpx.AsyncClient | None = None @@ -22,14 +33,11 @@ def _get_client() -> httpx.AsyncClient: async def authenticate_user(username: str, password: str) -> dict | None: """Authenticate a user via Jellyfin. Returns user info + token or None.""" client = _get_client() - auth_header = ( - 'MediaBrowser Client="Movie Night", Device="Web", DeviceId="movie-night-app", Version="1.0.0"' - ) try: res = await client.post( "/Users/AuthenticateByName", json={"Username": username, "Pw": password}, - headers={"X-Emby-Authorization": auth_header}, + headers={"Authorization": _authorization_header()}, ) if res.status_code == 200: data = res.json()