Files
Core_Be/Helpers/RequireWorkerKeyAttribute.cs
Dhananjaya99 bffc9b1686 first commit
2026-09-28 11:44:26 +05:30

56 lines
2.4 KiB
C#

using System.Security.Cryptography;
using System.Text;
using Fitness_core_BE.Models.IOs;
using Microsoft.AspNetCore.Mvc.Filters;
namespace Fitness_core_BE.Helpers
{
// Gates the subscription-billing worker endpoint behind a single shared secret in the
// X-Worker-Key header. Distinct from JwtMiddleware/CustomMiddleware (human/agent session
// auth) and from PaymentService:InternalApiKey (Core's own outbound key to Payment-Service) —
// this authenticates the trusted scheduler calling back into Core. Writes the 401/503
// response directly (like RequiresPermissionAttribute) rather than throwing, because Core
// has no global exception handler to turn a thrown exception into the right status code on
// this unauthenticated route.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class RequireWorkerKeyAttribute : Attribute, IAsyncActionFilter
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
var configuration = context.HttpContext.RequestServices.GetService(typeof(IConfiguration)) as IConfiguration;
var configuredKey = configuration?["Worker:InternalApiKey"];
if (string.IsNullOrWhiteSpace(configuredKey))
{
await WriteErrorAsync(context, 503, "Worker:InternalApiKey is not configured.");
return;
}
var providedKey = context.HttpContext.Request.Headers["X-Worker-Key"].FirstOrDefault();
if (string.IsNullOrWhiteSpace(providedKey) || !FixedTimeEquals(providedKey, configuredKey))
{
await WriteErrorAsync(context, 401, "Invalid worker key.");
return;
}
await next();
}
private static async Task WriteErrorAsync(ActionExecutingContext context, int statusCode, string message)
{
context.HttpContext.Response.StatusCode = statusCode;
await context.HttpContext.Response.WriteAsJsonAsync(new ApiResponse<object>
{
StatusCode = statusCode,
Message = message,
Data = null
});
}
private static bool FixedTimeEquals(string a, string b)
{
return CryptographicOperations.FixedTimeEquals(Encoding.UTF8.GetBytes(a), Encoding.UTF8.GetBytes(b));
}
}
}