using IdentityModel; using xIds.Interfaces; using xCommons.Constants; using xCommons.Extensions; using System.Threading.Tasks; using System.Security.Claims; using System.Text.Encodings.Web; using xIdentityService.Constants; using System.Collections.Generic; using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging; using Microsoft.AspNetCore.Authentication; namespace xIds.Providers { /// /// an Authentication Handler for ApiKey's based App's ... /// public class XApiKeyAuthenticationHandler : AuthenticationHandler { private readonly IXApplicationProvider applicationProvider; // public string HeaderName { get; } = XHeader.ApiKey.GetStringValue(); public string AuthenticationScheme { get; } = XAuthenticationScheme.XApiKey.GetStringValue(); public XApiKeyAuthenticationHandler( UrlEncoder encoder, ISystemClock clock, ILoggerFactory logger, IXApplicationProvider applicationProvider, IOptionsMonitor options ) : base(options, logger, encoder, clock) { this.applicationProvider = applicationProvider; } /// /// Handle Authentication ... /// /// protected override async Task HandleAuthenticateAsync() { // var apiKeyHeader = HeaderName; if (!Request.Headers.ContainsKey(apiKeyHeader)) { return AuthenticateResult.NoResult(); } // var apiKey = Request.Headers[apiKeyHeader].ToString(); if (apiKey.IsNullOrEmpty()) { return AuthenticateResult.NoResult(); } // Extract Client IP ... var clientIP = Request.HttpContext.Connection.RemoteIpAddress?.ToString(); // // Validating ApiKey ... var validationResult = await applicationProvider .ValidateApiKey( apiKey: apiKey, clientIP: clientIP ); if (validationResult.Errors.HasChild()) { // var message = validationResult.Errors.ToListString('\n'); return AuthenticateResult.Fail(message); } // // Creating Claims ... var claims = new List { // // Owner Identifier of API Key ... new(ClaimTypes.Name, validationResult.OwnerId), new(JwtClaimTypes.Subject, validationResult.OwnerId), // // Application Id ... new(XCustomClaims.ApplicationId, validationResult.ApplicationId.ToString()), // // Authentication Type ... new(XCustomClaims.AuthType, "apikey"), }; // // Add Scopes ... if (validationResult.Scopes != null) { foreach (var scope in validationResult.Scopes) { claims.Add(new Claim(JwtClaimTypes.Scope, scope)); } } // // Create Principal and Ticket ... var identity = new ClaimsIdentity(claims, Scheme.Name); var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, Scheme.Name); // return AuthenticateResult.Success(ticket); } } }