using System.Security.Claims; using System.Text.Encodings.Web; using Femto.Api.Sessions; using Femto.Common; using Femto.Modules.Auth.Application; using Femto.Modules.Auth.Application.Commands.ValidateSession; using Femto.Modules.Auth.Errors; using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Options; namespace Femto.Api.Auth; internal class SessionAuthenticationHandler( IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, IAuthenticationModule authModule, CurrentUserContext currentUserContext ) : AuthenticationHandler(options, logger, encoder) { protected override async Task HandleAuthenticateAsync() { var sessionId = this.Request.Cookies["session"]; if (string.IsNullOrWhiteSpace(sessionId)) return AuthenticateResult.NoResult(); try { var result = await authModule.PostCommand(new ValidateSessionCommand(sessionId)); var claims = new List { new(ClaimTypes.Name, result.Username), new("sub", result.UserId.ToString()), new("user_id", result.UserId.ToString()), }; var identity = new ClaimsIdentity(claims, this.Scheme.Name); var principal = new ClaimsPrincipal(identity); this.Context.SetSession(result.Session); currentUserContext.CurrentUser = new CurrentUser(result.UserId, result.Username); return AuthenticateResult.Success( new AuthenticationTicket(principal, this.Scheme.Name) ); } catch (InvalidSessionError) { return AuthenticateResult.Fail("Invalid session"); } } }