using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Text.Encodings.Web; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace Lidarr.Http.Authentication { public class ApiKeyAuthenticationOptions : AuthenticationSchemeOptions { public const string DefaultScheme = "API Key"; public string Scheme => DefaultScheme; public string AuthenticationType = DefaultScheme; public string HeaderName { get; set; } public string QueryName { get; set; } public string ApiKey { get; set; } } public class ApiKeyAuthenticationHandler : AuthenticationHandler { public ApiKeyAuthenticationHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { } private string ParseApiKey() { // Try query parameter if (Request.Query.TryGetValue(Options.QueryName, out var value)) { return value.FirstOrDefault(); } // No ApiKey query parameter found try headers if (Request.Headers.TryGetValue(Options.HeaderName, out var headerValue)) { return headerValue.FirstOrDefault(); } return Request.Headers["Authorization"].FirstOrDefault()?.Replace("Bearer ", ""); } protected override Task HandleAuthenticateAsync() { var providedApiKey = ParseApiKey(); if (string.IsNullOrWhiteSpace(providedApiKey)) { return Task.FromResult(AuthenticateResult.NoResult()); } if (Options.ApiKey == providedApiKey) { var claims = new List { new Claim("ApiKey", "true") }; var identity = new ClaimsIdentity(claims, Options.AuthenticationType); var identities = new List { identity }; var principal = new ClaimsPrincipal(identities); var ticket = new AuthenticationTicket(principal, Options.Scheme); return Task.FromResult(AuthenticateResult.Success(ticket)); } return Task.FromResult(AuthenticateResult.NoResult()); } protected override Task HandleChallengeAsync(AuthenticationProperties properties) { Response.StatusCode = 401; return Task.CompletedTask; } protected override Task HandleForbiddenAsync(AuthenticationProperties properties) { Response.StatusCode = 403; return Task.CompletedTask; } } }