diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs index 58421aaf1..18bea59ad 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs @@ -146,11 +146,17 @@ namespace Emby.Server.Implementations.HttpServer.Security { return true; } + if (authAttribtues.AllowLocalOnly && request.IsLocal) { return true; } + if (authAttribtues.IgnoreLegacyAuth) + { + return true; + } + return false; } diff --git a/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs b/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs index 26f7d9d2d..a0c9c3f5a 100644 --- a/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs +++ b/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs @@ -37,13 +37,20 @@ namespace Jellyfin.Api.Auth /// protected override Task HandleAuthenticateAsync() { - var authenticatedAttribute = new AuthenticatedAttribute(); + var authenticatedAttribute = new AuthenticatedAttribute + { + IgnoreLegacyAuth = true + }; + try { var user = _authService.Authenticate(Request, authenticatedAttribute); if (user == null) { - return Task.FromResult(AuthenticateResult.Fail("Invalid user")); + return Task.FromResult(AuthenticateResult.NoResult()); + // TODO return when legacy API is removed. + // Don't spam the log with "Invalid User" + // return Task.FromResult(AuthenticateResult.Fail("Invalid user")); } var claims = new[] diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 1c7fcbc06..387977ec4 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -10,6 +10,7 @@ using Jellyfin.Api.Auth.RequiresElevationPolicy; using Jellyfin.Api.Constants; using Jellyfin.Api.Controllers; using Jellyfin.Server.Formatters; +using Jellyfin.Server.Models; using MediaBrowser.Common.Json; using MediaBrowser.Model.Entities; using Microsoft.AspNetCore.Authentication; @@ -72,7 +73,12 @@ namespace Jellyfin.Server.Extensions /// The MVC builder. public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, string baseUrl) { - return serviceCollection.AddMvc(opts => + return serviceCollection + .AddCors(options => + { + options.AddPolicy(ServerCorsPolicy.DefaultPolicyName, ServerCorsPolicy.DefaultPolicy); + }) + .AddMvc(opts => { opts.UseGeneralRoutePrefix(baseUrl); opts.OutputFormatters.Insert(0, new CamelCaseJsonProfileFormatter()); diff --git a/Jellyfin.Server/Models/ServerCorsPolicy.cs b/Jellyfin.Server/Models/ServerCorsPolicy.cs new file mode 100644 index 000000000..ae010c042 --- /dev/null +++ b/Jellyfin.Server/Models/ServerCorsPolicy.cs @@ -0,0 +1,30 @@ +using Microsoft.AspNetCore.Cors.Infrastructure; + +namespace Jellyfin.Server.Models +{ + /// + /// Server Cors Policy. + /// + public static class ServerCorsPolicy + { + /// + /// Default policy name. + /// + public const string DefaultPolicyName = "DefaultCorsPolicy"; + + /// + /// Default Policy. Allow Everything. + /// + public static readonly CorsPolicy DefaultPolicy = new CorsPolicy + { + // Allow any origin + Origins = { "*" }, + + // Allow any method + Methods = { "*" }, + + // Allow any header + Headers = { "*" } + }; + } +} \ No newline at end of file diff --git a/Jellyfin.Server/Startup.cs b/Jellyfin.Server/Startup.cs index 7c49afbfc..bd2887e4a 100644 --- a/Jellyfin.Server/Startup.cs +++ b/Jellyfin.Server/Startup.cs @@ -1,5 +1,6 @@ using Jellyfin.Server.Extensions; using Jellyfin.Server.Middleware; +using Jellyfin.Server.Models; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using Microsoft.AspNetCore.Builder; @@ -68,9 +69,10 @@ namespace Jellyfin.Server // TODO app.UseMiddleware(); app.Use(serverApplicationHost.ExecuteWebsocketHandlerAsync); - // TODO use when old API is removed: app.UseAuthentication(); + app.UseAuthentication(); app.UseJellyfinApiSwagger(_serverConfigurationManager); app.UseRouting(); + app.UseCors(ServerCorsPolicy.DefaultPolicyName); app.UseAuthorization(); app.UseEndpoints(endpoints => { diff --git a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs index 29fb81e32..9f2743ea1 100644 --- a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs +++ b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs @@ -52,6 +52,8 @@ namespace MediaBrowser.Controller.Net return (Roles ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); } + public bool IgnoreLegacyAuth { get; set; } + public bool AllowLocalOnly { get; set; } } @@ -63,5 +65,7 @@ namespace MediaBrowser.Controller.Net bool AllowLocalOnly { get; } string[] GetRoles(); + + bool IgnoreLegacyAuth { get; } } } diff --git a/tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs index 3b3d03c8b..437dfa410 100644 --- a/tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs +++ b/tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs @@ -88,7 +88,9 @@ namespace Jellyfin.Api.Tests.Auth var authenticateResult = await _sut.AuthenticateAsync(); Assert.False(authenticateResult.Succeeded); - Assert.Equal("Invalid user", authenticateResult.Failure.Message); + Assert.True(authenticateResult.None); + // TODO return when legacy API is removed. + // Assert.Equal("Invalid user", authenticateResult.Failure.Message); } [Fact]