HMAC Validation (ASP.NET Core)
The Middleware Class
using System.Security.Cryptography;
using System.Text;
using Microsoft.Extensions.Primitives;
public class HmacAuthenticationMiddleware(RequestDelegate next, string secretKey)
{
private readonly RequestDelegate next = next;
private readonly string secretKey = secretKey;
public async Task Invoke(HttpContext context)
{
// Extract the HMAC signature from the Authorization header
if (!context.Request.Headers.TryGetValue("Authorization", out StringValues authHeader))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Missing Authorization Header");
return;
}
// The Authorization header should be in the format: HMAC <signature>
string[] authParts = authHeader.ToString().Split(' ');
if (authParts.Length != 2 || authParts[0] != "HMAC")
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Invalid Authorization Header Format");
return;
}
string providedSignature = authParts[1];
// Calculate the HMAC of the request
string calculatedSignature = await ComputeHmacSignature(context, secretKey);
// Compare the provided signature with the calculated one
if (!providedSignature.Equals(calculatedSignature, StringComparison.OrdinalIgnoreCase))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Invalid Signature");
return;
}
// Call the next middleware in the pipeline
await next(context);
}
private static async Task<string> ComputeHmacSignature(HttpContext context, string secretKey)
{
// Read the request content
context.Request.EnableBuffering();
var requestBody = await new StreamReader(context.Request.Body).ReadToEndAsync();
context.Request.Body.Position = 0;
// Compute the HMAC SHA256 hash
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secretKey));
byte[] hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(requestBody));
return Convert.ToBase64String(hash);
}
}Extension Method for Middleware
Register the Middleware
Last updated