aegis-api/Aegis.API/Auth/UserResolutionMiddleware.cs

54 lines
2.0 KiB
C#

using System.Security.Claims;
using Aegis.Application.Abstractions;
using Microsoft.Extensions.Caching.Memory;
namespace Aegis.API.Auth;
public class UserResolutionMiddleware(RequestDelegate next, IMemoryCache cache)
{
// TTL do cache (ajuste como quiser)
private static readonly TimeSpan CacheTtl = TimeSpan.FromHours(1);
public async Task InvokeAsync(HttpContext ctx, IUserIdentityRepository repo, CancellationToken ct)
{
// Só roda para requests autenticadas
if (ctx.User?.Identity?.IsAuthenticated == true)
{
var sub = ctx.User.FindFirstValue("sub");
var iss = ctx.User.FindFirstValue("iss");
if (!string.IsNullOrWhiteSpace(sub) && !string.IsNullOrWhiteSpace(iss))
{
var cacheKey = $"aegis_uid|{iss}|{sub}";
if (!cache.TryGetValue(cacheKey, out string? userIdValue))
{
var displayName = ctx.User.FindFirstValue("name")
?? ctx.User.FindFirstValue("preferred_username");
var email = ctx.User.FindFirstValue("email");
var userId = await repo.GetOrCreateAsync(sub, iss, displayName, email, ct);
userIdValue = userId.Value;
cache.Set(
cacheKey,
userIdValue,
new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = CacheTtl,
SlidingExpiration = TimeSpan.FromMinutes(15)
});
}
// Injeta claim aegis_uid se não existir
if (ctx.User.FindFirst("aegis_uid") is null && userIdValue is not null)
{
if (ctx.User.Identity is ClaimsIdentity identity)
identity.AddClaim(new Claim("aegis_uid", userIdValue));
}
}
}
await next(ctx);
}
}