API Key Authentication
Moka.Auth provides API key authentication for securing machine-to-machine communication and service integrations.
Basic Setup
Enable API key authentication in your Program.cs:
builder.Services.AddMokaAuth(options =>{ options.Authentication = new AuthenticationOptions { EnableApiKey = true };
options.ApiKey = new ApiKeyOptions { HeaderName = "X-Api-Key", QueryStringKey = "api_key", AllowQueryString = false, RequireHttps = true };});Or via appsettings.json:
{ "MokaAuth": { "Authentication": { "EnableApiKey": true }, "ApiKey": { "HeaderName": "X-Api-Key", "QueryStringKey": "api_key", "AllowQueryString": false, "RequireHttps": true } }}API Key Management
Creating API Keys
Use the IApiKeyService to create and manage API keys:
public class ApiKeyController : Controller{ private readonly IApiKeyService _apiKeyService; private readonly IUserService _userService;
[HttpPost("create")] [Authorize(Policy = "ApiKeyManagement")] public async Task<IActionResult> CreateApiKey(ApiKeyCreateModel model) { var key = new ApiKey { Name = model.Name, Description = model.Description, ExpiresAt = model.ExpiresAt, Roles = model.Roles, Permissions = model.Permissions, Metadata = model.Metadata, AllowedIps = model.AllowedIps, AllowedOrigins = model.AllowedOrigins };
var result = await _apiKeyService.CreateAsync(key); if (result.Succeeded) { // Important: Store this value securely, it won't be accessible again var rawKeyValue = result.KeyValue; return Ok(new { Id = result.KeyId, Value = rawKeyValue }); }
return BadRequest(result.Errors); }}Managing API Keys
List and manage existing API keys:
[ApiController][Route("api/keys")]public class ApiKeyController : Controller{ private readonly IApiKeyService _apiKeyService;
[HttpGet] [Authorize(Policy = "ApiKeyManagement")] public async Task<IActionResult> ListKeys([FromQuery] ApiKeyFilter filter) { var keys = await _apiKeyService.ListAsync(new ApiKeyFilter { Status = filter.Status, ExpiresAfter = filter.ExpiresAfter, CreatedAfter = filter.CreatedAfter, Search = filter.Search, Page = filter.Page, PageSize = filter.PageSize });
return Ok(keys); }
[HttpPut("{id}")] [Authorize(Policy = "ApiKeyManagement")] public async Task<IActionResult> UpdateKey(string id, ApiKeyUpdateModel model) { var result = await _apiKeyService.UpdateAsync(id, key => { key.Name = model.Name; key.Description = model.Description; key.ExpiresAt = model.ExpiresAt; key.IsEnabled = model.IsEnabled; key.AllowedIps = model.AllowedIps; key.AllowedOrigins = model.AllowedOrigins; });
if (result.Succeeded) { return Ok(); }
return BadRequest(result.Errors); }
[HttpDelete("{id}")] [Authorize(Policy = "ApiKeyManagement")] public async Task<IActionResult> RevokeKey(string id) { var result = await _apiKeyService.RevokeAsync(id); if (result.Succeeded) { return Ok(); }
return BadRequest(result.Errors); }}Advanced Features
Key Validation Options
Configure key validation rules:
builder.Services.AddMokaAuth(options =>{ options.ApiKey = new ApiKeyOptions { // Basic settings HeaderName = "X-Api-Key", QueryStringKey = "api_key",
// Validation RequireHttps = true, ValidateExpiration = true, ValidateStatus = true, ValidateOrigin = true, ValidateIpAddress = true,
// Rate limiting EnableRateLimiting = true, RateLimitingOptions = new RateLimitingOptions { Window = TimeSpan.FromMinutes(1), MaxRequests = 100, UseDistributedCache = true },
// Security MinKeyLength = 32, MaxKeyLength = 64, KeyFormat = ApiKeyFormat.Base64, HashAlgorithm = "PBKDF2" };});Custom Key Generation
Implement custom key generation logic:
builder.Services.AddMokaAuth(options =>{ options.ApiKey = new ApiKeyOptions { // Custom key generation KeyGenerator = new ApiKeyGenerator { Prefix = "mk", Format = ApiKeyFormat.Base64, Length = 32, Segments = 3, Separator = ".", IncludeChecksum = true } };});Events
Handle API key authentication events:
builder.Services.AddMokaAuth(options =>{ options.ApiKey = new ApiKeyOptions { Events = new ApiKeyEvents { OnValidating = async context => { // Custom validation logic var key = context.ApiKey; var request = context.HttpContext.Request;
// Example: Check if request is from allowed service if (!await IsAllowedService(request.Headers["Service-Name"])) { context.Fail("Invalid service"); } },
OnValidated = async context => { // Post-validation actions var key = context.ApiKey; await UpdateLastUsed(key.Id); },
OnFailed = async context => { // Handle validation failure var error = context.Error; await LogFailedAttempt(context.HttpContext, error); } } };});Using API Keys
HTTP Requests
Include the API key in the request header:
GET /api/data HTTP/1.1Host: api.example.comX-Api-Key: mk.YOUR_API_KEY_HEREHTTP Client
Configure an HTTP client to use API keys:
public class ApiClient{ private readonly HttpClient _client;
public ApiClient(string apiKey) { _client = new HttpClient(); _client.DefaultRequestHeaders.Add("X-Api-Key", apiKey); }
public async Task<T> GetAsync<T>(string endpoint) { var response = await _client.GetAsync(endpoint); response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<T>(); }}