using Microsoft.Extensions.Primitives; namespace Nexus.Api.Services; public static class RequestAuthorizationHelper { public sealed record AgentHeaderResolution( string? AgentId, bool HeaderProvided, bool IsRecognized, bool CredentialVerified, bool IdentityHintAuthorized); public static bool IsAuthenticatedService(HttpContext httpContext, IConfiguration configuration) => (httpContext.User.Identity?.IsAuthenticated == true && httpContext.User.IsInRole("Service")) || HasValidServiceKey(httpContext, configuration); public static bool HasVerifiedAuthentication(HttpContext httpContext, IConfiguration configuration) => httpContext.User.Identity?.IsAuthenticated == true || HasValidServiceKey(httpContext, configuration); public static bool IsPrivilegedUser(HttpContext httpContext) => httpContext.User.Identity?.IsAuthenticated == true && (httpContext.User.IsInRole("owner") || httpContext.User.IsInRole("admin")); public static bool CanUseAgentIdentityHint(HttpContext httpContext, IConfiguration configuration) => IsAuthenticatedService(httpContext, configuration) || IsPrivilegedUser(httpContext); public static async Task ResolveAllowedAgentHeaderAsync( HttpContext httpContext, IAgentService agentService, IConfiguration configuration, CancellationToken ct) => (await ResolveAgentHeaderAsync(httpContext, agentService, configuration, ct)).AgentId; public static async Task ResolveAgentHeaderAsync( HttpContext httpContext, IAgentService agentService, IConfiguration configuration, CancellationToken ct) { var headerValue = httpContext.Request.Headers["X-Agent-Id"].FirstOrDefault(); if (string.IsNullOrWhiteSpace(headerValue)) return new AgentHeaderResolution( null, HeaderProvided: false, IsRecognized: false, CredentialVerified: HasVerifiedAuthentication(httpContext, configuration), IdentityHintAuthorized: CanUseAgentIdentityHint(httpContext, configuration)); var allowed = AgentIdentityCatalog.BuildAllowedActorIds(await agentService.GetAllowedAgentIdsAsync(ct)); var normalized = AgentIdentityCatalog.NormalizeActorId(headerValue, allowed); var credentialVerified = HasVerifiedAuthentication(httpContext, configuration); var identityHintAuthorized = CanUseAgentIdentityHint(httpContext, configuration); return new AgentHeaderResolution( identityHintAuthorized ? normalized : null, HeaderProvided: true, IsRecognized: normalized is not null, CredentialVerified: credentialVerified, IdentityHintAuthorized: identityHintAuthorized); } public static bool HasValidServiceKey(HttpContext httpContext, IConfiguration configuration) { var configuredApiKey = configuration["NexusApiKey"]; if (string.IsNullOrWhiteSpace(configuredApiKey)) return false; if (!httpContext.Request.Headers.TryGetValue("X-Nexus-Api-Key", out StringValues providedKey)) return false; return string.Equals(configuredApiKey, providedKey.FirstOrDefault(), StringComparison.Ordinal); } }