Recently I wanted to create a custom authentication, to authorize by ApiKey and ApiSecret in the header. To create such a middleware to affect the entire services of the system I created the following:
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
public class ApiKeyMiddleware
{
private readonly RequestDelegate _next;
private readonly IConfiguration _config;
private readonly ILogger _logger;
public ApiKeyMiddleware(RequestDelegate next, IConfiguration config, ILogger<ApiKeyMiddleware> logger)
{
_next = next;
_config = config;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
if (!context.Request.Headers.ContainsKey("X-Api-Key") || !context.Request.Headers.ContainsKey("X-Api-Secret"))
{
_logger.LogWarning("Missing API key or secret.");
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Unauthorized");
return;
}
var apiKey = context.Request.Headers["X-Api-Key"].FirstOrDefault();
var apiSecret = context.Request.Headers["X-Api-Secret"].FirstOrDefault();
if (!IsAuthorized(apiKey, apiSecret))
{
_logger.LogWarning($"Invalid API key or secret: {apiKey}");
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Unauthorized");
return;
}
await _next(context);
}
private bool IsAuthorized(string apiKey, string apiSecret)
{
var storedApiKey = _config.GetValue<string>("ApiKey");
var storedApiSecret = _config.GetValue<string>("ApiSecret");
if (apiKey == storedApiKey && apiSecret == storedApiSecret)
{
return true;
}
return false;
}
}
In the InvokeAsync method of this middleware, I check if the request headers contain the X-Api-Key and X-Api-Secret headers. If they are missing, I return a 401 Unauthorized response. If they are present, I check if the provided key and secret match the ones stored in the configuration. If they match, I continue with the request processing. If they don't match, I return a 401 Unauthorized response. Next, I added this middleware to the pipeline in the Configure method of Startup.cs:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// ...
app.UseMiddleware<ApiKeyMiddleware>();
// ...
}
Finally, I added the ApiKey and ApiSecret configuration values to the appsettings.json file:
{
"ApiKey": "your-api-key",
"ApiSecret": "your-api-secret"
}
This was just a simple form of what I created for the project as it has more challenges. Hope it helps!