CustomAuthenticationHandler.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. using System.Globalization;
  2. using System.Security.Claims;
  3. using System.Text.Encodings.Web;
  4. using System.Threading.Tasks;
  5. using Jellyfin.Api.Constants;
  6. using Jellyfin.Data.Enums;
  7. using MediaBrowser.Controller.Authentication;
  8. using MediaBrowser.Controller.Net;
  9. using Microsoft.AspNetCore.Authentication;
  10. using Microsoft.Extensions.Logging;
  11. using Microsoft.Extensions.Options;
  12. namespace Jellyfin.Api.Auth
  13. {
  14. /// <summary>
  15. /// Custom authentication handler wrapping the legacy authentication.
  16. /// </summary>
  17. public class CustomAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
  18. {
  19. private readonly IAuthService _authService;
  20. private readonly ILogger<CustomAuthenticationHandler> _logger;
  21. /// <summary>
  22. /// Initializes a new instance of the <see cref="CustomAuthenticationHandler" /> class.
  23. /// </summary>
  24. /// <param name="authService">The jellyfin authentication service.</param>
  25. /// <param name="options">Options monitor.</param>
  26. /// <param name="logger">The logger.</param>
  27. /// <param name="encoder">The url encoder.</param>
  28. /// <param name="clock">The system clock.</param>
  29. public CustomAuthenticationHandler(
  30. IAuthService authService,
  31. IOptionsMonitor<AuthenticationSchemeOptions> options,
  32. ILoggerFactory logger,
  33. UrlEncoder encoder,
  34. ISystemClock clock) : base(options, logger, encoder, clock)
  35. {
  36. _authService = authService;
  37. _logger = logger.CreateLogger<CustomAuthenticationHandler>();
  38. }
  39. /// <inheritdoc />
  40. protected override Task<AuthenticateResult> HandleAuthenticateAsync()
  41. {
  42. try
  43. {
  44. var authorizationInfo = _authService.Authenticate(Request);
  45. var role = UserRoles.User;
  46. if (authorizationInfo.IsApiKey || authorizationInfo.User.HasPermission(PermissionKind.IsAdministrator))
  47. {
  48. role = UserRoles.Administrator;
  49. }
  50. var claims = new[]
  51. {
  52. new Claim(ClaimTypes.Name, authorizationInfo.User?.Username ?? string.Empty),
  53. new Claim(ClaimTypes.Role, role),
  54. new Claim(InternalClaimTypes.UserId, authorizationInfo.UserId.ToString("N", CultureInfo.InvariantCulture)),
  55. new Claim(InternalClaimTypes.DeviceId, authorizationInfo.DeviceId),
  56. new Claim(InternalClaimTypes.Device, authorizationInfo.Device),
  57. new Claim(InternalClaimTypes.Client, authorizationInfo.Client),
  58. new Claim(InternalClaimTypes.Version, authorizationInfo.Version),
  59. new Claim(InternalClaimTypes.Token, authorizationInfo.Token),
  60. new Claim(InternalClaimTypes.IsApiKey, authorizationInfo.IsApiKey.ToString(CultureInfo.InvariantCulture))
  61. };
  62. var identity = new ClaimsIdentity(claims, Scheme.Name);
  63. var principal = new ClaimsPrincipal(identity);
  64. var ticket = new AuthenticationTicket(principal, Scheme.Name);
  65. return Task.FromResult(AuthenticateResult.Success(ticket));
  66. }
  67. catch (AuthenticationException ex)
  68. {
  69. _logger.LogDebug(ex, "Error authenticating with {Handler}", nameof(CustomAuthenticationHandler));
  70. return Task.FromResult(AuthenticateResult.NoResult());
  71. }
  72. catch (SecurityException ex)
  73. {
  74. return Task.FromResult(AuthenticateResult.Fail(ex));
  75. }
  76. }
  77. }
  78. }