Files
tiku-backend.net/Tiku.Api/Security/AuditingAuthorizationMiddlewareResultHandler.cs
xiong 33375a38d7
Some checks failed
ci / release-gate (push) Has been cancelled
refactor(architecture): harden module boundaries
2026-08-04 12:10:36 +08:00

55 lines
2.4 KiB
C#

using System.Text.Json;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Policy;
using Tiku.Application.Backoffice;
using Tiku.Application.Security;
namespace Tiku.Api.Security;
internal sealed class AuditingAuthorizationMiddlewareResultHandler(
IServiceScopeFactory scopeFactory,
ILogger<AuditingAuthorizationMiddlewareResultHandler> logger) : IAuthorizationMiddlewareResultHandler
{
private readonly AuthorizationMiddlewareResultHandler fallback = new();
public async Task HandleAsync(
RequestDelegate next,
HttpContext context,
AuthorizationPolicy policy,
PolicyAuthorizationResult authorizeResult)
{
if (authorizeResult.Forbidden && context.User.Identity?.IsAuthenticated == true)
try
{
await using var scope = scopeFactory.CreateAsyncScope();
var auditService = scope.ServiceProvider.GetRequiredService<IOperationAuditService>();
await auditService.WriteAsync(new BackofficeOperationAuditCommand(
Guid.TryParse(context.User.FindFirst(TikuClaimTypes.TenantId)?.Value, out var tenantId)
? tenantId
: null,
Guid.TryParse(context.User.FindFirst(TikuClaimTypes.UserId)?.Value, out var userId)
? userId
: null,
"authorization.access_denied",
"http_endpoint",
context.Request.Path,
JsonSerializer.SerializeToElement(new
{
context.Request.Method,
Path = context.Request.Path.Value,
Realm = context.User.FindFirst(TikuClaimTypes.Realm)?.Value,
Failure = authorizeResult.AuthorizationFailure?.FailureReasons.Select(reason => reason.Message)
.ToArray()
}),
context.Connection.RemoteIpAddress?.ToString(),
context.Request.Headers.UserAgent.ToString()), context.RequestAborted);
}
catch (Exception exception)
{
logger.LogWarning(exception, "Failed to persist authorization denial audit event.");
}
await fallback.HandleAsync(next, context, policy, authorizeResult);
}
}