CustomAuthenticationHandler.cs 3.8 KB

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