init
This commit is contained in:
64
Filters/WebhookAuthFilter.cs
Normal file
64
Filters/WebhookAuthFilter.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System.Net;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Alchegos.HCI.Filters;
|
||||
|
||||
public class WebhookAuthFilter : IEndpointFilter
|
||||
{
|
||||
private readonly ILogger<WebhookAuthFilter> _logger;
|
||||
|
||||
public WebhookAuthFilter(ILogger<WebhookAuthFilter> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
public async ValueTask<object?> InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next)
|
||||
{
|
||||
var expectedToken = Environment.GetEnvironmentVariable("WebhookAuth__RequiredApiToken");
|
||||
var allowedOrigin = Environment.GetEnvironmentVariable("WebhookAuth__AllowedOrigin");
|
||||
|
||||
if (string.IsNullOrEmpty(expectedToken) || string.IsNullOrEmpty(allowedOrigin))
|
||||
{
|
||||
_logger.LogCritical("Required environment variables 'WebhookAuth__RequiredApiToken' or 'WebhookAuth__AllowedOrigin' are not set.");
|
||||
return Results.StatusCode((int)HttpStatusCode.InternalServerError);
|
||||
}
|
||||
|
||||
var httpContext = context.HttpContext;
|
||||
|
||||
if (!httpContext.Request.Headers.TryGetValue("X-Api-Key", out StringValues receivedTokenValues) || receivedTokenValues.Count == 0)
|
||||
{
|
||||
_logger.LogWarning("Webhook request rejected: Missing 'X-Api-Key' header.");
|
||||
return Results.Unauthorized();
|
||||
}
|
||||
var receivedToken = receivedTokenValues.ToString();
|
||||
if (!SecureCompare(receivedToken, expectedToken))
|
||||
{
|
||||
_logger.LogWarning("Webhook request rejected: Invalid API Token provided.");
|
||||
return Results.Unauthorized();
|
||||
}
|
||||
|
||||
if (!httpContext.Request.Headers.TryGetValue("Origin", out StringValues originValues) || originValues.Count == 0)
|
||||
{
|
||||
_logger.LogWarning("Webhook request rejected: Missing 'Origin' header.");
|
||||
return Results.Forbid();
|
||||
}
|
||||
var origin = originValues.ToString();
|
||||
if (!origin.Equals(allowedOrigin, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_logger.LogWarning("Webhook request rejected: Origin '{ReceivedOrigin}' is not allowed. Expected '{AllowedOrigin}'.", origin, allowedOrigin);
|
||||
return Results.Forbid();
|
||||
}
|
||||
|
||||
_logger.LogInformation("Webhook request from Origin '{Origin}' authenticated successfully.", origin);
|
||||
return await next(context);
|
||||
}
|
||||
|
||||
private static bool SecureCompare(string a, string b)
|
||||
{
|
||||
a ??= string.Empty;
|
||||
b ??= string.Empty;
|
||||
if (a.Length != b.Length) return false;
|
||||
int diff = 0;
|
||||
for (int i = 0; i < a.Length; i++) diff |= a[i] ^ b[i];
|
||||
return diff == 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user