diff --git a/docs/containers.md b/docs/containers.md
index f4a216d..303c966 100644
--- a/docs/containers.md
+++ b/docs/containers.md
@@ -21,9 +21,14 @@ and finally run the image:
docker run -p 8080:8080 helldivers2-api
```
+> [!WARNING]
+> If you get an error message when starting the container similar `System.ArgumentNullException: Value cannot be null. (Parameter 's')`
+> read the section below about [Configuring API keys for the self-hosted version](#configuring-api-keys-for-the-self-hosted-version).
+> You can read more details on this [here](https://github.com/helldivers-2/api/issues/90)
+
### Building the container with OpenAPI
-By default the OpenAPI specifications aren't bundled in the container image,
-you can enable OpenAPI support by building the container with these flags:
+By default, the OpenAPI specifications aren't bundled in the container image.
+You can enable OpenAPI support by building the container with these flags:
```shell
docker build --build-arg="OPENAPI=true" -f ./src/Helldivers-2-API/Dockerfile -t helldivers2-api .
```
@@ -63,6 +68,45 @@ docker run -p 8080:8080 -e "Helldivers__Synchronization__IntervalSeconds=10" hel
You can read more about using environment variables to override configuration [here](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-8.0#naming-of-environment-variables)
+### Configuring API keys for the self-hosted version
+The API ships with an API key mechanism that allows you to generate API keys that can override the specified rate limits.
+This feature is enabled by default, but requires a valid signing key to generate and validate API keys.
+
+For security reasons we don't ship default API keys (as that would open anyone who forgets to change them to DDOS attacks).
+If you don't want to bother with API keys (for example because you configured your own rate limits as shown [below](#overriding-rate-limits))
+you can disable them by passing the following parameter to your Docker run command:
+```shell
+docker run -p 8080:8080 -e "Helldivers__API__Authentication__Enabled=false" helldivers2-api
+```
+If you'd like to enable API keys, you'll have to set a signing key. It's *required* this key is 32 bits and formatted as
+base 64 (for examples in a couple languages see [Generating an API signing key](#generating-an-api-signing-key)).
+
+Once you have your signing key, pass it to the container using the `Helldivers__API__Authentication__SigningKey` variable:
+```shell
+docker run -p 8080:8080 -e "Helldivers__API__Authentication__SigningKey=YourSigningKey" helldivers2-api
+```
+
+### Generating an API signing key
+Elixir
+```elixir
+32
+|> :crypto.strong_rand_bytes()
+|> Base.encode64()
+```
+
+### Generating an API key
+When you run the API locally (*not in a container*) you have access to an extra endpoint: `/dev/token`.
+This endpoint generates an API key that you can use to make requests to any API instance that has the same signing key.
+
+It takes 2 parameters:
+- `name` which is the name of the client for which you are generating a token (it's used for metrics and logging).
+- `limit` this is the new rate limit that will be set when the API key is used
+
+for example: `/dev/token?name=dealloc&limit=999` will generate an API token for a client called `dealloc` that can make `999` requests per time window.
+
+> [!WARNING]
+> This endpoint **requires** a valid signing key to be configured, if you don't have one see [Configuring API keys for the self-hosted version](#configuring-api-keys-for-the-self-hosted-version)
+
### Overriding rate limits
You can override the rate limits by overriding the following configuration:
```json
@@ -84,4 +128,4 @@ Increasing the `RateLimit`, decreasing the `RateLimitWindow` or both will effect
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!).
+by sponsoring this project! (if you self-host you can generate your own keys too!).
diff --git a/src/Helldivers-2-API/Configuration/AuthenticationConfiguration.cs b/src/Helldivers-2-API/Configuration/AuthenticationConfiguration.cs
index 8ad4b20..293da05 100644
--- a/src/Helldivers-2-API/Configuration/AuthenticationConfiguration.cs
+++ b/src/Helldivers-2-API/Configuration/AuthenticationConfiguration.cs
@@ -5,6 +5,11 @@
///
public sealed class AuthenticationConfiguration
{
+ ///
+ /// Whether the API authentication is enabled or disabled.
+ ///
+ public bool Enabled { get; set; } = true;
+
///
/// A list of valid issuers of authentication tokens.
///
diff --git a/src/Helldivers-2-API/Program.cs b/src/Helldivers-2-API/Program.cs
index a9dc761..4000aa7 100644
--- a/src/Helldivers-2-API/Program.cs
+++ b/src/Helldivers-2-API/Program.cs
@@ -117,23 +117,27 @@
#if DEBUG
IdentityModelEventSource.ShowPII = true;
#endif
-builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
-{
- var config = new AuthenticationConfiguration();
- builder.Configuration.GetSection("Helldivers:API:Authentication").Bind(config);
- options.TokenValidationParameters = new()
+var authConfig = new AuthenticationConfiguration();
+builder.Configuration.GetSection("Helldivers:API:Authentication").Bind(authConfig);
+if (authConfig.Enabled)
+{
+ builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
- ValidIssuers = config.ValidIssuers,
- ValidAudiences = config.ValidAudiences,
- IssuerSigningKey = new SymmetricSecurityKey(Convert.FromBase64String(config.SigningKey)),
- ValidateIssuer = true,
- ValidateAudience = true,
- ValidateLifetime = true,
- ValidateIssuerSigningKey = true
- };
-});
-builder.Services.AddAuthorization();
+
+ options.TokenValidationParameters = new()
+ {
+ ValidIssuers = authConfig.ValidIssuers,
+ ValidAudiences = authConfig.ValidAudiences,
+ IssuerSigningKey = new SymmetricSecurityKey(Convert.FromBase64String(authConfig.SigningKey)),
+ ValidateIssuer = true,
+ ValidateAudience = true,
+ ValidateLifetime = true,
+ ValidateIssuerSigningKey = true
+ };
+ });
+ builder.Services.AddAuthorization();
+}
// Swagger is generated at compile time, so we don't include Swagger dependencies in Release builds.
#if DEBUG
diff --git a/src/Helldivers-2-API/appsettings.Development.json b/src/Helldivers-2-API/appsettings.Development.json
index 21d5cbd..3bc86a6 100644
--- a/src/Helldivers-2-API/appsettings.Development.json
+++ b/src/Helldivers-2-API/appsettings.Development.json
@@ -4,7 +4,8 @@
"Default": "Information",
"Helldivers": "Trace",
"Microsoft.AspNetCore": "Warning",
- "System.Net.Http.HttpClient.ApiService": "Warning"
+ "System.Net.Http.HttpClient.ApiService": "Warning",
+ "Microsoft.AspNetCore.Authentication": "Trace"
}
},
"Helldivers": {
diff --git a/src/Helldivers-2-API/appsettings.json b/src/Helldivers-2-API/appsettings.json
index 10e4c0b..2e2214c 100644
--- a/src/Helldivers-2-API/appsettings.json
+++ b/src/Helldivers-2-API/appsettings.json
@@ -2,10 +2,9 @@
"Logging": {
"LogLevel": {
"Default": "Information",
- "Helldivers": "Trace",
+ "Helldivers": "Information",
"System.Net.Http.HttpClient": "Warning",
- "Microsoft.AspNetCore": "Warning",
- "Microsoft.AspNetCore.Authentication": "Trace"
+ "Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
@@ -14,6 +13,7 @@
"RateLimit": 5,
"RateLimitWindow": 10,
"Authentication": {
+ "Enabled": true,
"ValidIssuers": ["dealloc"],
"ValidAudiences": [
"https://api.helldivers2.dev"