diff --git a/src/Jellyfin.Plugin.Multilang/Api/MultilangController.cs b/src/Jellyfin.Plugin.Multilang/Api/MultilangController.cs index c9dfebf..1e40602 100644 --- a/src/Jellyfin.Plugin.Multilang/Api/MultilangController.cs +++ b/src/Jellyfin.Plugin.Multilang/Api/MultilangController.cs @@ -309,6 +309,7 @@ public sealed class MultilangController : ControllerBase var upstreamSw = Stopwatch.StartNew(); var http = _httpClientFactory.CreateClient(); using var request = new HttpRequestMessage(HttpMethod.Get, proxyRequest.Upstream); + request.Headers.TryAddWithoutValidation("Authorization", $"MediaBrowser Token=\"{token}\""); request.Headers.TryAddWithoutValidation("X-Emby-Token", token); request.Headers.TryAddWithoutValidation("X-MediaBrowser-Token", token); using var response = await http.SendAsync(request, cancellationToken).ConfigureAwait(false); @@ -1250,10 +1251,6 @@ public sealed class MultilangController : ControllerBase if (string.IsNullOrWhiteSpace(token)) return null; - var tokenUserId = await GetUserIdFromJellyfinApiAsync(token).ConfigureAwait(false); - if (!string.IsNullOrWhiteSpace(tokenUserId)) - return tokenUserId; - var remoteEndpoint = HttpContext.Connection.RemoteIpAddress?.ToString() ?? string.Empty; var deviceId = info?.DeviceId ?? string.Empty; var session = await _sessionManager.GetSessionByAuthenticationToken(token, deviceId, remoteEndpoint).ConfigureAwait(false); @@ -1274,34 +1271,6 @@ public sealed class MultilangController : ControllerBase : null; } - private async Task GetUserIdFromJellyfinApiAsync(string token) - { - var baseUri = $"{Request.Scheme}://{Request.Host}{Request.PathBase}"; - var usersMe = new UriBuilder(new Uri(new Uri(baseUri), "/Users/Me")); - usersMe.Query = Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString( - string.Empty, - "api_key", - token).TrimStart('?'); - - var http = _httpClientFactory.CreateClient(); - using var request = new HttpRequestMessage(HttpMethod.Get, usersMe.Uri); - request.Headers.TryAddWithoutValidation("X-Emby-Token", token); - request.Headers.TryAddWithoutValidation("X-MediaBrowser-Token", token); - using var response = await http.SendAsync(request, HttpContext.RequestAborted).ConfigureAwait(false); - if (!response.IsSuccessStatusCode) - return null; - - await using var stream = await response.Content.ReadAsStreamAsync(HttpContext.RequestAborted).ConfigureAwait(false); - using var doc = await JsonDocument.ParseAsync(stream, cancellationToken: HttpContext.RequestAborted).ConfigureAwait(false); - if (!doc.RootElement.TryGetProperty("Id", out var idProperty)) - return null; - - var raw = idProperty.GetString(); - return Guid.TryParse(raw, out var guid) - ? guid.ToString("N") - : raw?.Length == 32 && raw.All(Uri.IsHexDigit) ? raw.ToLowerInvariant() : null; - } - private async Task IsRequesterAdminAsync() { var info = await _authorizationContext.GetAuthorizationInfo(HttpContext).ConfigureAwait(false); diff --git a/src/Jellyfin.Plugin.Multilang/Configuration/shared.js b/src/Jellyfin.Plugin.Multilang/Configuration/shared.js index 4dd9290..048f38c 100644 --- a/src/Jellyfin.Plugin.Multilang/Configuration/shared.js +++ b/src/Jellyfin.Plugin.Multilang/Configuration/shared.js @@ -19,6 +19,7 @@ const t = token() || qs.get("token") || qs.get("api_key") || ""; const h = { "Content-Type": "application/json" }; if (t) { + h.Authorization = `MediaBrowser Token="${t}"`; h["X-Emby-Token"] = t; h["X-MediaBrowser-Token"] = t; } @@ -31,6 +32,7 @@ const h = {}; if (contentType) h["Content-Type"] = contentType; if (t) { + h.Authorization = `MediaBrowser Token="${t}"`; h["X-Emby-Token"] = t; h["X-MediaBrowser-Token"] = t; } diff --git a/src/Jellyfin.Plugin.Multilang/Services/ItemsProxyRequestBuilder.cs b/src/Jellyfin.Plugin.Multilang/Services/ItemsProxyRequestBuilder.cs index 021bad5..143f85e 100644 --- a/src/Jellyfin.Plugin.Multilang/Services/ItemsProxyRequestBuilder.cs +++ b/src/Jellyfin.Plugin.Multilang/Services/ItemsProxyRequestBuilder.cs @@ -71,7 +71,6 @@ public static class ItemsProxyRequestBuilder } var cacheQuery = QueryHelpers.AddQueryString(string.Empty, pairs).TrimStart('?'); - pairs.Add(KeyValuePair.Create("api_key", token)); builder.Query = QueryHelpers.AddQueryString(string.Empty, pairs).TrimStart('?'); var normalizedForCache = builder.Path + (cacheQuery.Length > 0 ? "?" + cacheQuery : string.Empty); return new ItemsProxyRequest( diff --git a/src/Jellyfin.Plugin.Multilang/wwwroot/inject.js b/src/Jellyfin.Plugin.Multilang/wwwroot/inject.js index 53af922..f7ea06e 100644 --- a/src/Jellyfin.Plugin.Multilang/wwwroot/inject.js +++ b/src/Jellyfin.Plugin.Multilang/wwwroot/inject.js @@ -311,7 +311,9 @@ function refreshItems(itemIds) { const token = getClientToken(); - const headers = token ? { "X-Emby-Token": token, "X-MediaBrowser-Token": token } : {}; + const headers = token + ? { Authorization: `MediaBrowser Token="${token}"`, "X-Emby-Token": token, "X-MediaBrowser-Token": token } + : {}; itemIds.forEach((itemId) => { fetch(`${BASE_PATH}/Multilang/RefreshItem/${itemId}?includeChildren=true${token ? `&token=${encodeURIComponent(token)}` : ""}`, { method: "POST", headers }); }); diff --git a/tests/Jellyfin.Plugin.Multilang.Tests/ItemsProxyRequestBuilderTests.cs b/tests/Jellyfin.Plugin.Multilang.Tests/ItemsProxyRequestBuilderTests.cs index ae2d7e7..0f14b12 100644 --- a/tests/Jellyfin.Plugin.Multilang.Tests/ItemsProxyRequestBuilderTests.cs +++ b/tests/Jellyfin.Plugin.Multilang.Tests/ItemsProxyRequestBuilderTests.cs @@ -22,8 +22,8 @@ public sealed class ItemsProxyRequestBuilderTests Assert.NotNull(result); Assert.Equal($"/Users/{UserId}/Items", result.Upstream.AbsolutePath); - Assert.Contains("api_key=token", result.Upstream.Query); Assert.DoesNotContain("api_key=old", result.Upstream.Query); + Assert.DoesNotContain("api_key", result.Upstream.Query, StringComparison.OrdinalIgnoreCase); Assert.DoesNotContain("api_key", result.NormalizedUrlForCache, StringComparison.OrdinalIgnoreCase); Assert.Contains("userId=" + UserId, result.NormalizedUrlForCache); }