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"