ApiKeyEndpointFilter.cs 1.1 KB

1234567891011121314151617181920212223242526272829303132333435
  1. using System.Security.Cryptography;
  2. using System.Text;
  3. namespace RackPeek.Web.Api;
  4. public class ApiKeyEndpointFilter(IConfiguration configuration) : IEndpointFilter
  5. {
  6. private const string ApiKeyHeaderName = "X-Api-Key";
  7. public async ValueTask<object?> InvokeAsync(
  8. EndpointFilterInvocationContext context,
  9. EndpointFilterDelegate next)
  10. {
  11. var expectedKey = configuration["RPK_API_KEY"];
  12. if (string.IsNullOrWhiteSpace(expectedKey))
  13. return Results.StatusCode(503);
  14. if (!context.HttpContext.Request.Headers.TryGetValue(ApiKeyHeaderName, out var providedKey)
  15. || !SecureEquals(providedKey.ToString(), expectedKey))
  16. {
  17. return Results.Json(new { error = "Unauthorized" }, statusCode: 401);
  18. }
  19. return await next(context);
  20. }
  21. private static bool SecureEquals(string a, string b)
  22. {
  23. var aBytes = Encoding.UTF8.GetBytes(a);
  24. var bBytes = Encoding.UTF8.GetBytes(b);
  25. return CryptographicOperations.FixedTimeEquals(aBytes, bBytes);
  26. }
  27. }