using System.Security.Claims; using System.Text.Encodings.Web; using System.Text.Json; using Femto.Api.Sessions; using Femto.Common; using Femto.Modules.Auth.Application; using Femto.Modules.Auth.Application.Dto; using Femto.Modules.Auth.Application.Interface.ValidateSession; using Femto.Modules.Auth.Errors; using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Options; using Microsoft.OpenApi.Extensions; namespace Femto.Api.Auth; internal class SessionAuthenticationHandler( IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, IAuthModule 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(); var userJson = this.Request.Cookies["user"]; if (string.IsNullOrWhiteSpace(userJson)) return AuthenticateResult.Fail("Invalid user"); var user = JsonSerializer.Deserialize(userJson); if (user is null) return AuthenticateResult.Fail("Invalid user"); var rememberMe = this.Request.Cookies["rememberme"]; try { var result = await authModule.Command( new ValidateSessionCommand(sessionId, user, rememberMe) ); var claims = new List { new(ClaimTypes.Name, user.Username), new("sub", user.Id.ToString()), new("user_id", user.Id.ToString()), }; claims.AddRange(user.Roles.Select(role => new Claim(ClaimTypes.Role, role.ToString()))); var identity = new ClaimsIdentity(claims, this.Scheme.Name); var principal = new ClaimsPrincipal(identity); this.Context.SetSession(result.SessionDto, user, Logger); currentUserContext.CurrentUser = new CurrentUser( user.Id, user.Username, result.SessionDto.SessionId, rememberMe ); return AuthenticateResult.Success( new AuthenticationTicket(principal, this.Scheme.Name) ); } catch (InvalidSessionError) { return AuthenticateResult.Fail("Invalid session"); } } }