Files
monorepo/LCU.Library.Internal.Security/LCU.Library.Internal.ApiSecurity/Attributes/ApiKeyAttribute.cs
T
2026-03-24 09:49:29 -05:00

130 lines
6.1 KiB
C#

using LCU.Library.Internal.ApiSecurity.Constants;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using LCU.Library.Internal.ApiSecurity.Enums;
using LCU.Library.Internal.ApiSecurity.Models;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace LCU.Library.Internal.ApiSecurity.Attributes;
[AttributeUsage(validOn: AttributeTargets.Method)]
public class ApiKeyAttribute : Attribute, IAsyncActionFilter
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
var apiSecurityConfiguration = context.HttpContext.RequestServices.GetRequiredService<ApiSecurityConfiguration>();
var logger = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>().CreateLogger(GetType().Name);
if (apiSecurityConfiguration.ExternalApiKeySet.Any())
{
if (!context.HttpContext.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.Result = new ContentResult()
{
StatusCode = 401,
Content = AuthMessages.NotProvidedMessage(HeaderKeys.ApiKey)
};
return;
default:
throw new Exception("Invalid ApiKeyAuthenticationFailureBehavior Value");
}
}
if (!context.HttpContext.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.Result = new ContentResult()
{
StatusCode = 401,
Content = 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.Result = new ContentResult()
{
StatusCode = 401,
Content = 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.Result = new ContentResult()
{
StatusCode = 401,
Content = 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.Result = new ContentResult()
{
StatusCode = 401,
Content = AuthMessages.EmptyKeySetMessage("ExternalApiKeySet")
};
return;
default:
throw new Exception("Invalid ApiKeyAuthenticationFailureBehavior Value");
}
}
await next();
}
}