Repository navigation
Home
A .NET library for supporting API key-based access control in ASP.NET Core applications.
- Supports .NET 10, .NET 9 and .NET 8.
- Integrates easily into ASP.NET Core using
services.AddApiKeyValidation(...). - Provides attribute-based protection using
[ApiKey(typeof(MyApiKeyPolicyProvider))]to secure controllers or actions. - Offers configurable key extraction through Authorization headers (e.g.
ApiKey), custom headers (e.g.X-API-KEY), and query parameters. - Supports customizable policies that define allowed API keys, IP ranges (CIDR), and local-only access.
- Includes built-in error handling that returns proper HTTP status codes or RFC 9457 Problem Details responses.
- Uses an extensible design so you can override or replace extractors, policies, and error factories through dependency injection.
Add the package reference to your ASP.NET Core project:
dotnet add package Enbrea.ApiKeyIn your Program.cs or Startup.cs:
using Enbrea.ApiKey;
var builder = WebApplication.CreateBuilder(args);
// Register API key validation
builder.Services.AddApiKeyValidation(options =>
{
// Optional configuration
options.AcceptedHeaderNames = new[] { "X-API-KEY" };
options.AcceptedAuthSchemes = new[] { "ApiKey" };
options.AcceptedQueryParamNames = new[] { "api_key" };
});
// Optionally switch to ProblemDetails-based responses
builder.Services.AddSingleton<ProblemDetailsFactory, DefaultProblemDetailsFactory>();
builder.Services.AddApiKeyValidation(o => { }).UseProblemDetailsFactory();
var app = builder.Build();
app.MapControllers();
app.Run();Implement an IApiKeyPolicyProvider to define the rules for validation.
using Enbrea.ApiKey;
public class MyPolicyProvider : IApiKeyPolicyProvider
{
public IApiKeyPolicy Get()
{
return new ApiKeyPolicy
{
Keys = new[] { "secret123", "another-key" },
AllowLocal = true,
PrivateOnly = false,
AllowCidrs = new[] { "10.0.0.0/8" }
};
}
}You can load keys dynamically from a database, configuration file, or remote source if needed.
Decorate controllers or actions that should require an API key:
using Enbrea.ApiKey;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
[ApiKey(typeof(MyPolicyProvider))]
public class DemoController : ControllerBase
{
[HttpGet("status")]
public IActionResult GetStatus()
{
return Ok(new { status = "OK" });
}
}Responsible for reading the API key from the incoming HTTP request.
The extractor can check:
- The Authorization header with configured schemes (e.g., ApiKey my-secret)
- Custom headers (e.g., X-API-KEY)
- Query string parameters (e.g., ?api_key=my-secret)
Example custom configuration:
options.AcceptedHeaderNames = new[] { "X-ACCESS-KEY", "X-API-KEY" };
options.AcceptedQueryParamNames = new[] { "key", "api_key" };Defines the validation rules.
| Property | Type | Description |
|---|---|---|
| Keys | string[] | List of valid API keys. |
| AllowLocal | bool | Allows local requests (127.0.0.1 or ::1). |
| AllowCidrs | string[] | Allows specific IP ranges (CIDR notation). |
| PrivateOnly | bool | Restricts endpoint access to local/private IPs only. |
Creates the HTTP responses for invalid or missing keys.
Two implementations are available:
| Factory | Description |
|---|---|
| ApiKeyDefaultErrorFactory | Returns plain status results (401, 404, 500). |
| ApiKeyProblemDetailsFactory | Returns RFC 9457–compliant ProblemDetails JSON responses. |
To enable ProblemDetails:
builder.Services.AddSingleton<ProblemDetailsFactory, DefaultProblemDetailsFactory>();
builder.Services.AddApiKeyValidation(o => { }).UseProblemDetailsFactory();Allow local requests and specific API keys:
new ApiKeyPolicy
{
Keys = new[] { "local123" },
AllowLocal = true
};Allow only internal networks:
new ApiKeyPolicy
{
PrivateOnly = true,
AllowCidrs = new[] { "192.168.0.0/16", "10.0.0.0/8" }
};Disable API key for internal use only:
new ApiKeyPolicy
{
PrivateOnly = true
};If you want to create a minimal API with ASP.NET Core:
using Enbrea.ApiKey;
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddApiKeyValidation(o =>
{
o.AcceptedHeaderNames = new[] { "X-API-KEY" };
o.AcceptedAuthSchemes = new[] { "ApiKey" };
});
var app = builder.Build();
app.MapControllers();
app.MapGet("/public", () => "Public endpoint");
app.MapGet("/protected", [ApiKey(typeof(MyPolicyProvider))] () => "Protected endpoint");
app.Run();You can implement your own extractor if you use a nonstandard API key format:
public class CustomHeaderExtractor : IApiKeyExtractor
{
public bool TryGetApiKey(HttpRequest request, out string? apiKey)
{
apiKey = request.Headers["X-CUSTOM-HEADER"];
return !string.IsNullOrEmpty(apiKey);
}
}Register it in DI:
services.AddSingleton<IApiKeyExtractor, CustomHeaderExtractor>();You can override how error responses are created:
public class JsonErrorFactory : IApiKeyErrorResultFactory
{
public IActionResult Create(HttpContext context, ApiKeyError error)
{
return new JsonResult(new { message = "Access denied", code = error.ToString() })
{
StatusCode = StatusCodes.Status401Unauthorized
};
}
}Register it in DI:
services.AddSingleton<IApiKeyErrorResultFactory, JsonErrorFactory>();