using System.Security.Claims; using System.Text; using System.Text.Encodings.Web; using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Options; using Newtonsoft.Json; using SVSim.Database.Enums; using SVSim.Database.Models; using SVSim.Database.Repositories.Viewer; using SVSim.EmulatedEntrypoint.Constants; using SVSim.EmulatedEntrypoint.Extensions; using SVSim.EmulatedEntrypoint.Models.Dtos.Requests; using SVSim.EmulatedEntrypoint.Services; namespace SVSim.EmulatedEntrypoint.Security.SteamSessionAuthentication; public class SteamSessionAuthenticationHandler : AuthenticationHandler { private readonly SteamSessionService _sessionService; private readonly IViewerRepository _viewerRepository; public SteamSessionAuthenticationHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, SteamSessionService sessionService, IViewerRepository viewerRepository) : base(options, logger, encoder) { _sessionService = sessionService; _viewerRepository = viewerRepository; } protected async override Task HandleAuthenticateAsync() { byte[] requestBytes; try { using (var requestBytesStream = new MemoryStream()) { // Reset request stream Request.Body.Seek(0, SeekOrigin.Begin); await Request.Body.CopyToAsync(requestBytesStream); requestBytes = requestBytesStream.ToArray(); // Reset request stream Request.Body.Seek(0, SeekOrigin.Begin); } } catch (Exception e) { return AuthenticateResult.Fail("Failed to read request body."); } // Convert bytes to json string requestString = Encoding.UTF8.GetString(requestBytes); BaseRequest? requestJson = JsonConvert.DeserializeObject(requestString); if (requestJson is null) { return AuthenticateResult.Fail("Invalid request body."); } // Check steam session validity bool sessionIsValid = _sessionService.IsTicketValidForUser(requestJson.SteamSessionTicket, requestJson.SteamId); if (!sessionIsValid) { return AuthenticateResult.Fail("Invalid ticket."); } Viewer? viewer = await _viewerRepository.GetViewerBySocialConnection(SocialAccountType.Steam, requestJson.SteamId); if (viewer is null) { return AuthenticateResult.Fail("User not found."); } // Add viewer to context Context.SetViewer(viewer); // Build identity ClaimsIdentity identity = new ClaimsIdentity(SteamAuthenticationConstants.SchemeName); identity.AddClaim(new Claim(ClaimTypes.Name, viewer.DisplayName)); identity.AddClaim(new Claim(ShadowverseClaimTypes.ShortUdidClaim, viewer.ShortUdid.ToString())); identity.AddClaim(new Claim(ShadowverseClaimTypes.ViewerIdClaim, viewer.Id.ToString())); identity.AddClaim(new Claim(SteamAuthenticationConstants.SteamIdClaim, requestJson.SteamId.ToString())); // Build and return final ticket AuthenticationTicket ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), SteamAuthenticationConstants.SchemeName); return AuthenticateResult.Success(ticket); } }