using khmereid_backend.Data; using khmereid_backend.Dtos; using System.Security.Claims; using System.Text.Encodings.Web; using khmereid_backend.Services; using Microsoft.Extensions.Options; using Microsoft.AspNetCore.Authentication; using System.Text.Json; using Ory.Kratos.Client.Client; namespace khmereid_backend.Integrations; public class KratosMiddleware : AuthenticationHandler { private readonly AppDbContext _db; private readonly AuthService _authService; public KratosMiddleware( AppDbContext db, UrlEncoder encoder, ILoggerFactory logger, AuthService authService, IOptionsMonitor options ) : base(options, logger, encoder) { _db = db; _authService = authService; } protected override async Task HandleAuthenticateAsync() { var authHeader = Request.Headers["Authorization"].ToString(); if (string.IsNullOrWhiteSpace(authHeader) || !authHeader.StartsWith("Bearer ")) return AuthenticateResult.NoResult(); var token = authHeader.Substring("Bearer ".Length).Trim(); try { var session = await _authService.GetMeAsync(token); Console.WriteLine("---------------"); Console.WriteLine(JsonSerializer.Serialize(session, new JsonSerializerOptions { WriteIndented = true })); var identityId = Guid.Parse(session.Data!.Id); var localUser = _db.Users.FirstOrDefault(u => u.IdentityId == identityId); if (localUser == null) return AuthenticateResult.Fail("User not found in local database"); var userDto = new UserDto { Id = localUser.Id, Phone = localUser.Phone, IdentityId = localUser.IdentityId }; Context.Items["UserDto"] = userDto; var identity = new ClaimsIdentity( [new Claim(ClaimTypes.NameIdentifier, userDto.Id.ToString())], Scheme.Name ); var principal = new ClaimsPrincipal(identity); return AuthenticateResult.Success(new AuthenticationTicket(principal, Scheme.Name)); } catch (Exception ex) { Logger.LogError(ex, "Failed to authenticate Kratos session"); return AuthenticateResult.Fail("Invalid Kratos session token"); } } }