diff --git a/docs/containers.md b/docs/containers.md index 303c966..b15a862 100644 --- a/docs/containers.md +++ b/docs/containers.md @@ -129,3 +129,24 @@ make to the application. Alternatively, if you use the hosted versions you can request an API key that allows for higher rate limits by sponsoring this project! (if you self-host you can generate your own keys too!). + +# Disabling the client validation +If you run the container and navigate to it in your browser +you might come across the following message: +```json +{"message":"The X-Super-Client and X-Super-Contact headers are required"} +``` + +This is because by default the API will validate all requests send `X-Super-Client` and `X-Super-Contact` +headers along. You can disable this behaviour by setting the following flag: +```json +{ + "Helldivers": { + "API": { + "ValidateClients": false + } + } +} +``` +Or through environment flags with `-e Helldivers__API__ValidateClients` + diff --git a/src/Helldivers-2-API/Configuration/ApiConfiguration.cs b/src/Helldivers-2-API/Configuration/ApiConfiguration.cs index 1dadb48..69a338f 100644 --- a/src/Helldivers-2-API/Configuration/ApiConfiguration.cs +++ b/src/Helldivers-2-API/Configuration/ApiConfiguration.cs @@ -20,6 +20,11 @@ public sealed class ApiConfiguration /// public string Blacklist { get; set; } = string.Empty; + /// + /// Whether X-Super-Client and X-Super-Contact headers are validated. + /// + public bool ValidateClients { get; set; } = true; + /// /// Contains the for the API. /// diff --git a/src/Helldivers-2-API/Middlewares/RateLimitMiddleware.cs b/src/Helldivers-2-API/Middlewares/RateLimitMiddleware.cs index 6c2db5c..7e4f820 100644 --- a/src/Helldivers-2-API/Middlewares/RateLimitMiddleware.cs +++ b/src/Helldivers-2-API/Middlewares/RateLimitMiddleware.cs @@ -2,8 +2,11 @@ using Helldivers.API.Extensions; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; +using Microsoft.Net.Http.Headers; using System.Net; using System.Security.Claims; +using System.Text; +using System.Text.Json; using System.Threading.RateLimiting; namespace Helldivers.API.Middlewares; @@ -26,6 +29,12 @@ IMemoryCache cache /// public async Task InvokeAsync(HttpContext context, RequestDelegate next) { + if (IsValidRequest(context) is false) + { + await RejectRequest(context); + return; + } + var limiter = GetRateLimiter(context); using var lease = await limiter.AcquireAsync(permitCount: 1, context.RequestAborted); if (limiter.GetStatistics() is { } statistics) @@ -45,6 +54,18 @@ public async Task InvokeAsync(HttpContext context, RequestDelegate next) await next(context); } + /// + /// Checks if the request is "valid" (contains the correct X-Super-* headers). + /// + private bool IsValidRequest(HttpContext context) + { + if (options.Value.ValidateClients is false) + return true; + + return context.Request.Headers.ContainsKey(Constants.CLIENT_HEADER_NAME) + && context.Request.Headers.ContainsKey(Constants.CONTACT_HEADER_NAME); + } + private RateLimiter GetRateLimiter(HttpContext http) { if (http.User.Identity?.IsAuthenticated ?? false) @@ -86,4 +107,19 @@ private RateLimiter GetRateLimiterForUser(ClaimsPrincipal user) }); }) ?? throw new InvalidOperationException($"Creating rate limiter failed for {name}"); } + + private async Task RejectRequest(HttpContext context) + { + context.Response.StatusCode = StatusCodes.Status400BadRequest; + context.Response.Headers.WWWAuthenticate = "X-Super-Client"; + context.Response.ContentType = "application/json"; + + var writer = new Utf8JsonWriter(context.Response.Body); + writer.WriteStartObject(); + writer.WritePropertyName("message"); + writer.WriteStringValue("The X-Super-Client and X-Super-Contact headers are required"); + writer.WriteEndObject(); + + await writer.FlushAsync(context.RequestAborted); + } } diff --git a/src/Helldivers-2-API/appsettings.Development.json b/src/Helldivers-2-API/appsettings.Development.json index 3bc86a6..ebc03f0 100644 --- a/src/Helldivers-2-API/appsettings.Development.json +++ b/src/Helldivers-2-API/appsettings.Development.json @@ -10,6 +10,7 @@ }, "Helldivers": { "API": { + "ValidateClients": false, "Authentication": { "SigningKey": "I4eGmsXbDXfxlRo5N+w0ToRGN8aWSIaYWbZ2zMFqqnI=" }