diff --git a/src/Middlewares/ApiKeyMiddleware.cs b/src/Middlewares/ApiKeyMiddleware.cs index 9f41a61..3e4c989 100644 --- a/src/Middlewares/ApiKeyMiddleware.cs +++ b/src/Middlewares/ApiKeyMiddleware.cs @@ -1,12 +1,17 @@ -using DotEnv.Core; +using System.Text; +using System.Security.Cryptography; using Microsoft.AspNetCore.Authorization; +using DotEnv.Core; using SimpleResults; -using System.Net; namespace Playtesters.API.Middlewares; -public class ApiKeyMiddleware(RequestDelegate next) +public class ApiKeyMiddleware( + IEnvReader envReader, + RequestDelegate next) { + private readonly byte[] _apiKeyBytes = Encoding.UTF8.GetBytes(envReader["API_KEY"]); + public async Task InvokeAsync(HttpContext context) { var endpoint = context.GetEndpoint(); @@ -18,22 +23,25 @@ public async Task InvokeAsync(HttpContext context) if (!context.Request.Headers.TryGetValue("X-Api-Key", out var providedKey)) { - var response = Result.Unauthorized("Missing API Key."); - context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; - await context.Response.WriteAsJsonAsync(response); + await Unauthorized(context, "Missing API Key."); return; } - var envReader = new EnvReader(); - var apiKey = envReader["API_KEY"]; - if (!apiKey.Equals(providedKey)) + var providedKeyBytes = Encoding.UTF8.GetBytes(providedKey.ToString()); + + if (!CryptographicOperations.FixedTimeEquals(_apiKeyBytes, providedKeyBytes)) { - var response = Result.Unauthorized("Invalid API Key."); - context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; - await context.Response.WriteAsJsonAsync(response); + await Unauthorized(context, "Invalid API Key."); return; } await next(context); } + + private static async Task Unauthorized(HttpContext context, string message) + { + Result result = Result.Unauthorized(message); + context.Response.StatusCode = StatusCodes.Status401Unauthorized; + await context.Response.WriteAsJsonAsync(result); + } } diff --git a/src/Program.cs b/src/Program.cs index e7180a2..1f48e72 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -16,6 +16,7 @@ builder.Services.AddSwaggerWithApiKey(); builder.Services.AddServices(); builder.Services.AddExceptionHandler(); +builder.Services.AddSingleton(new EnvReader(envVars)); builder.Services.AddDbContext(options => options.UseSqlite($"Data Source={dataSource}"));