Skip to content

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.1
Host: api.example.com
X-Api-Key: mk.YOUR_API_KEY_HERE

HTTP 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>();
}
}