using System.Security.Claims;
namespace MyTelegram.Admin.Api.Middleware;
///
/// Middleware аутентификации для Admin API.
/// Для всех админских эндпоинтов требует API-ключ или токен.
///
public class AdminAuthMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
private readonly string _adminApiKey;
public AdminAuthMiddleware(RequestDelegate next, ILogger logger, IConfiguration configuration)
{
_next = next;
_logger = logger;
// Берём ключ из конфигурации или переменной окружения,
// значение по умолчанию пригодно только для разработки
_adminApiKey = configuration["ADMIN_API_KEY"]
?? Environment.GetEnvironmentVariable("ADMIN_API_KEY")
?? "CHANGE_ME_IN_PRODUCTION";
if (_adminApiKey == "CHANGE_ME_IN_PRODUCTION")
{
_logger.LogWarning("Using default Admin API key! Set ADMIN_API_KEY environment variable.");
}
else
{
_logger.LogInformation("Admin API authentication enabled with custom key");
}
}
public async Task InvokeAsync(HttpContext context)
{
var path = context.Request.Path.Value;
// Проверяем аутентификацию для всех эндпоинтов /api/*
if (path != null && path.StartsWith("/api/"))
{
// Сначала ищем ключ в заголовке X-Admin-API-Key
if (!context.Request.Headers.TryGetValue("X-Admin-API-Key", out var apiKey) ||
apiKey != _adminApiKey)
{
// Затем пробуем заголовок Authorization с Bearer-токеном
if (!context.Request.Headers.TryGetValue("Authorization", out var authHeader) ||
!authHeader.ToString().StartsWith("Bearer ") ||
authHeader.ToString().Substring(7) != _adminApiKey)
{
_logger.LogWarning("Unauthorized Admin API access attempt - IP: {IP}, Path: {Path}",
context.Connection.RemoteIpAddress, path);
context.Response.StatusCode = 401;
context.Response.ContentType = "application/json";
await context.Response.WriteAsJsonAsync(new
{
success = false,
error = "Unauthorized: Invalid or missing API key"
});
return;
}
}
_logger.LogDebug("Admin API access authorized - Path: {Path}", path);
}
await _next(context);
}
}