using System.Security.Claims; using Hutopy.Application.Common.Interfaces; using Hutopy.Infrastructure.Identity; using Hutopy.Infrastructure.Utils; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Newtonsoft.Json.Linq; namespace Hutopy.Web.Controllers; public class GoogleController( IIdentityService identityService, IHttpClientFactory httpClientFactory, IOptionsSnapshot jwtOptions) : Controller { [Microsoft.AspNetCore.Mvc.HttpPost("/api/google/sign-in")] public async Task SignIn([Microsoft.AspNetCore.Mvc.FromBody] GoogleSignInRequest request) { using var httpClient = httpClientFactory.CreateClient(); // Verify the token with Google var response = await httpClient.GetAsync($"https://www.googleapis.com/oauth2/v1/userinfo?access_token={request.AccessToken}"); if (!response.IsSuccessStatusCode) { return BadRequest("Invalid Google token."); } var userInfo = JObject.Parse(await response.Content.ReadAsStringAsync()); var email = userInfo["email"]?.ToString() ?? ""; var name = userInfo["name"]?.ToString() ?? ""; var givenName = userInfo["given_name"]?.ToString() ?? ""; var familyName = userInfo["family_name"]?.ToString() ?? ""; if (string.IsNullOrEmpty(email)) { return BadRequest("Google token did not contain an email."); } // Check if user exists or create a new one var user = await identityService.FindUserByEmailAsync(email); if (user == null) { await identityService.CreateUserAsync(email, email, givenName, familyName, RandomGenerator.RandomString(24)); user = await identityService.FindUserByEmailAsync(email); } if (user?.Id is null) { return BadRequest("Unable to find or create the user."); } // Sign in the user var claimsIdentity = new ClaimsIdentity( new List { new(ClaimTypes.Name, name), new(ClaimTypes.Email, email), new(ClaimTypes.GivenName, givenName), new(ClaimTypes.Surname, familyName) }, CookieAuthenticationDefaults.AuthenticationScheme); await HttpContext.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity)); var token = JwtTokenHelper.GenerateJwtToken( jwtOptions.Value.Lifetime, jwtOptions.Value.Issuer, jwtOptions.Value.Audience, jwtOptions.Value.Key, user.Id.ToString(), user.Email, user.Alias, user.FirstName, user.LastName, user.PortraitUrl); return Ok(new { accessToken = token, email }); } public class GoogleSignInRequest { public required string AccessToken { get; set; } } }