using ManagerService.Data; using ManagerService.Service; using ManagerService.Service.Services; using Microsoft.AspNetCore.Authentication; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System.Security.Claims; using System.Text.Encodings.Web; using System.Threading.Tasks; namespace ManagerService.Security { public class ApiKeyAuthenticationHandler : AuthenticationHandler { private const string HeaderName = "X-Api-Key"; private readonly MyInfoMateDbContext _db; public ApiKeyAuthenticationHandler( IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, MyInfoMateDbContext db) : base(options, logger, encoder) { _db = db; } protected override async Task HandleAuthenticateAsync() { if (!Request.Headers.TryGetValue(HeaderName, out var keyValue)) return AuthenticateResult.NoResult(); var value = keyValue.ToString(); var keyHash = TokensService.GenerateSHA256String(value); var apiKey = await _db.ApiKeys.FirstOrDefaultAsync(k => k.IsActive && (k.DateExpiration == null || k.DateExpiration > System.DateTime.UtcNow) && (k.Key == value || k.KeyHash == keyHash)); if (apiKey == null) return AuthenticateResult.Fail("Invalid API Key"); var claims = new[] { new Claim(Service.Security.ClaimTypes.InstanceId, apiKey.InstanceId), new Claim(Service.Security.ClaimTypes.AppType, apiKey.AppType.ToString()), new Claim(Service.Security.ClaimTypes.Permission, Service.Security.Permissions.AppRead), new Claim(Service.Security.ClaimTypes.Permission, Service.Security.Permissions.Viewer), }; var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, Scheme.Name)); return AuthenticateResult.Success(new AuthenticationTicket(principal, Scheme.Name)); } } }