ApiKeyEndpointFilter.cs 1.1 KB

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