aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Jellyfin.Api/Auth/CustomAuthenticationHandler.cs')
-rw-r--r--Jellyfin.Api/Auth/CustomAuthenticationHandler.cs84
1 files changed, 84 insertions, 0 deletions
diff --git a/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs b/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs
new file mode 100644
index 000000000..369e846ae
--- /dev/null
+++ b/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs
@@ -0,0 +1,84 @@
+using System.Globalization;
+using System.Security.Claims;
+using System.Text.Encodings.Web;
+using System.Threading.Tasks;
+using Jellyfin.Api.Constants;
+using Jellyfin.Data.Enums;
+using MediaBrowser.Controller.Authentication;
+using MediaBrowser.Controller.Net;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+
+namespace Jellyfin.Api.Auth
+{
+ /// <summary>
+ /// Custom authentication handler wrapping the legacy authentication.
+ /// </summary>
+ public class CustomAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
+ {
+ private readonly IAuthService _authService;
+ private readonly ILogger<CustomAuthenticationHandler> _logger;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CustomAuthenticationHandler" /> class.
+ /// </summary>
+ /// <param name="authService">The jellyfin authentication service.</param>
+ /// <param name="options">Options monitor.</param>
+ /// <param name="logger">The logger.</param>
+ /// <param name="encoder">The url encoder.</param>
+ /// <param name="clock">The system clock.</param>
+ public CustomAuthenticationHandler(
+ IAuthService authService,
+ IOptionsMonitor<AuthenticationSchemeOptions> options,
+ ILoggerFactory logger,
+ UrlEncoder encoder,
+ ISystemClock clock) : base(options, logger, encoder, clock)
+ {
+ _authService = authService;
+ _logger = logger.CreateLogger<CustomAuthenticationHandler>();
+ }
+
+ /// <inheritdoc />
+ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
+ {
+ try
+ {
+ var authorizationInfo = await _authService.Authenticate(Request).ConfigureAwait(false);
+ var role = UserRoles.User;
+ if (authorizationInfo.IsApiKey || authorizationInfo.User.HasPermission(PermissionKind.IsAdministrator))
+ {
+ role = UserRoles.Administrator;
+ }
+
+ var claims = new[]
+ {
+ new Claim(ClaimTypes.Name, authorizationInfo.User?.Username ?? string.Empty),
+ new Claim(ClaimTypes.Role, role),
+ new Claim(InternalClaimTypes.UserId, authorizationInfo.UserId.ToString("N", CultureInfo.InvariantCulture)),
+ new Claim(InternalClaimTypes.DeviceId, authorizationInfo.DeviceId),
+ new Claim(InternalClaimTypes.Device, authorizationInfo.Device),
+ new Claim(InternalClaimTypes.Client, authorizationInfo.Client),
+ new Claim(InternalClaimTypes.Version, authorizationInfo.Version),
+ new Claim(InternalClaimTypes.Token, authorizationInfo.Token),
+ new Claim(InternalClaimTypes.IsApiKey, authorizationInfo.IsApiKey.ToString(CultureInfo.InvariantCulture))
+ };
+
+ var identity = new ClaimsIdentity(claims, Scheme.Name);
+ var principal = new ClaimsPrincipal(identity);
+ var ticket = new AuthenticationTicket(principal, Scheme.Name);
+
+ return AuthenticateResult.Success(ticket);
+ }
+ catch (AuthenticationException ex)
+ {
+ _logger.LogDebug(ex, "Error authenticating with {Handler}", nameof(CustomAuthenticationHandler));
+ return AuthenticateResult.NoResult();
+ }
+ catch (SecurityException ex)
+ {
+ return AuthenticateResult.Fail(ex);
+ }
+ }
+ }
+}