CustomAuthenticationHandler.cs 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. using System.Globalization;
  2. using System.Security.Authentication;
  3. using System.Security.Claims;
  4. using System.Text.Encodings.Web;
  5. using System.Threading.Tasks;
  6. using Jellyfin.Api.Constants;
  7. using Jellyfin.Data.Enums;
  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. /// <summary>
  21. /// Initializes a new instance of the <see cref="CustomAuthenticationHandler" /> class.
  22. /// </summary>
  23. /// <param name="authService">The jellyfin authentication service.</param>
  24. /// <param name="options">Options monitor.</param>
  25. /// <param name="logger">The logger.</param>
  26. /// <param name="encoder">The url encoder.</param>
  27. /// <param name="clock">The system clock.</param>
  28. public CustomAuthenticationHandler(
  29. IAuthService authService,
  30. IOptionsMonitor<AuthenticationSchemeOptions> options,
  31. ILoggerFactory logger,
  32. UrlEncoder encoder,
  33. ISystemClock clock) : base(options, logger, encoder, clock)
  34. {
  35. _authService = authService;
  36. }
  37. /// <inheritdoc />
  38. protected override Task<AuthenticateResult> HandleAuthenticateAsync()
  39. {
  40. try
  41. {
  42. var authorizationInfo = _authService.Authenticate(Request);
  43. if (authorizationInfo == null)
  44. {
  45. return Task.FromResult(AuthenticateResult.NoResult());
  46. // TODO return when legacy API is removed.
  47. // Don't spam the log with "Invalid User"
  48. // return Task.FromResult(AuthenticateResult.Fail("Invalid user"));
  49. }
  50. var claims = new[]
  51. {
  52. new Claim(ClaimTypes.Name, authorizationInfo.User.Username),
  53. new Claim(ClaimTypes.Role, value: authorizationInfo.User.HasPermission(PermissionKind.IsAdministrator) ? UserRoles.Administrator : UserRoles.User),
  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. };
  61. var identity = new ClaimsIdentity(claims, Scheme.Name);
  62. var principal = new ClaimsPrincipal(identity);
  63. var ticket = new AuthenticationTicket(principal, Scheme.Name);
  64. return Task.FromResult(AuthenticateResult.Success(ticket));
  65. }
  66. catch (AuthenticationException ex)
  67. {
  68. return Task.FromResult(AuthenticateResult.Fail(ex));
  69. }
  70. catch (SecurityException ex)
  71. {
  72. return Task.FromResult(AuthenticateResult.Fail(ex));
  73. }
  74. }
  75. }
  76. }