using LCU.Library.Internal.ApiSecurity.Constants; using Microsoft.AspNetCore.Http; using LCU.Library.Internal.ApiSecurity.Enums; using LCU.Library.Internal.ApiSecurity.Models; using Microsoft.AspNetCore.Http.Extensions; using Microsoft.Extensions.Logging; namespace LCU.Library.Internal.ApiSecurity.Middleware { public class ApiKeyMiddleware { private readonly ApiSecurityConfiguration _apiSecurityConfiguration; private readonly ILogger _logger; private readonly RequestDelegate _next; public ApiKeyMiddleware(RequestDelegate next, ApiSecurityConfiguration apiSecurityConfiguration, ILoggerFactory loggerFactory) { _next = next; _apiSecurityConfiguration = apiSecurityConfiguration; _logger = loggerFactory.CreateLogger(GetType().Name); } public async Task InvokeAsync(HttpContext context) { var displayUrl = context.Request.GetDisplayUrl(); if (_apiSecurityConfiguration.ExternalApiKeySet.Any()) { if (!context.Request.Headers.TryGetValue(HeaderKeys.ApiKey, out var extractedApiKey)) { switch (_apiSecurityConfiguration.ApiKeyAuthenticationFailureBehavior) { case ApiKeyAuthenticationFailureBehavior.Warn: _logger.LogWarning(AuthMessages.NotProvidedMessage(HeaderKeys.ApiKey)); break; case ApiKeyAuthenticationFailureBehavior.Error: _logger.LogError(AuthMessages.NotProvidedMessage(HeaderKeys.ApiKey)); context.Response.StatusCode = 401; await context.Response.WriteAsync(AuthMessages.NotProvidedMessage(HeaderKeys.ApiKey)); return; default: throw new Exception("Invalid ApiKeyAuthenticationFailureBehavior Value"); } } if (!context.Request.Headers.TryGetValue(HeaderKeys.Client, out var extractedClient)) { switch (_apiSecurityConfiguration.ApiKeyAuthenticationFailureBehavior) { case ApiKeyAuthenticationFailureBehavior.Warn: _logger.LogWarning(AuthMessages.NotProvidedMessage(HeaderKeys.Client)); break; case ApiKeyAuthenticationFailureBehavior.Error: _logger.LogError(AuthMessages.NotProvidedMessage(HeaderKeys.Client)); context.Response.StatusCode = 401; await context.Response.WriteAsync(AuthMessages.NotProvidedMessage(HeaderKeys.Client)); return; default: throw new Exception("Invalid ApiKeyAuthenticationFailureBehavior Value"); } } if (!string.IsNullOrWhiteSpace(extractedClient)) { if (_apiSecurityConfiguration.ExternalApiKeySet.TryGetValue(extractedClient, out var apiKey)) { if (!apiKey.Equals(extractedApiKey)) { switch (_apiSecurityConfiguration.ApiKeyAuthenticationFailureBehavior) { case ApiKeyAuthenticationFailureBehavior.Warn: _logger.LogWarning(AuthMessages.AuthFailureMessage(extractedClient)); break; case ApiKeyAuthenticationFailureBehavior.Error: _logger.LogError(AuthMessages.AuthFailureMessage(extractedClient)); context.Response.StatusCode = 401; await context.Response.WriteAsync(AuthMessages.AuthFailureMessage(extractedClient)); return; default: throw new Exception("Invalid ApiKeyAuthenticationFailureBehavior Value"); } } _logger.LogInformation($"Valid auth received for Client: {extractedClient}"); } else { switch (_apiSecurityConfiguration.ApiKeyAuthenticationFailureBehavior) { case ApiKeyAuthenticationFailureBehavior.Warn: _logger.LogWarning(AuthMessages.ClientNotFoundMessage()); break; case ApiKeyAuthenticationFailureBehavior.Error: _logger.LogError(AuthMessages.ClientNotFoundMessage()); context.Response.StatusCode = 401; await context.Response.WriteAsync(AuthMessages.ClientNotFoundMessage()); return; default: throw new Exception("Invalid ApiKeyAuthenticationFailureBehavior Value"); } } } } else { switch (_apiSecurityConfiguration.ApiKeyAuthenticationFailureBehavior) { case ApiKeyAuthenticationFailureBehavior.Warn: _logger.LogWarning(AuthMessages.EmptyKeySetMessage("ExternalApiKeySet")); break; case ApiKeyAuthenticationFailureBehavior.Error: _logger.LogError(AuthMessages.EmptyKeySetMessage("ExternalApiKeySet")); context.Response.StatusCode = 401; await context.Response.WriteAsync(AuthMessages.EmptyKeySetMessage("ExternalApiKeySet")); return; default: throw new Exception("Invalid ApiKeyAuthenticationFailureBehavior Value"); } } await _next(context); } } }