Skip to content

Commit

Permalink
Add header validation to RateLimitMiddleware
Browse files Browse the repository at this point in the history
Implements validation for X-Super-Client and X-Super-Contact headers in the RateLimitMiddleware. Includes a configuration setting to enable or disable header validation.

see #94
  • Loading branch information
dealloc committed Nov 10, 2024
1 parent 9ee18da commit 7c0a8ae
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 0 deletions.
21 changes: 21 additions & 0 deletions docs/containers.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`

5 changes: 5 additions & 0 deletions src/Helldivers-2-API/Configuration/ApiConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ public sealed class ApiConfiguration
/// </summary>
public string Blacklist { get; set; } = string.Empty;

/// <summary>
/// Whether X-Super-Client and X-Super-Contact headers are validated.
/// </summary>
public bool ValidateClients { get; set; } = true;

/// <summary>
/// Contains the <see cref="AuthenticationConfiguration" /> for the API.
/// </summary>
Expand Down
36 changes: 36 additions & 0 deletions src/Helldivers-2-API/Middlewares/RateLimitMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -26,6 +29,12 @@ IMemoryCache cache
/// <inheritdoc />
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)
Expand All @@ -45,6 +54,18 @@ public async Task InvokeAsync(HttpContext context, RequestDelegate next)
await next(context);
}

/// <summary>
/// Checks if the request is "valid" (contains the correct X-Super-* headers).
/// </summary>
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)
Expand Down Expand Up @@ -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);
}
}
1 change: 1 addition & 0 deletions src/Helldivers-2-API/appsettings.Development.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
},
"Helldivers": {
"API": {
"ValidateClients": false,
"Authentication": {
"SigningKey": "I4eGmsXbDXfxlRo5N+w0ToRGN8aWSIaYWbZ2zMFqqnI="
}
Expand Down

0 comments on commit 7c0a8ae

Please sign in to comment.