using System.Runtime.Serialization; using System.Security.Claims; using System.Text.Json; using Elements.Data; using Elements.Data.Models; using Google.Apis.Auth; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace Elements.Backend.Controllers; [ApiController] [Route("[controller]/[action]")] public class AuthController : ControllerBase { private readonly IConfiguration _config; private readonly ApplicationDbContext _dbContext; public AuthController(IConfiguration config, ApplicationDbContext dbContext) { _config = config; _dbContext = dbContext; } public class LoginModel { public required string GoogleToken { get; init; } } [HttpPost] public async Task Login([FromBody] LoginModel model) { GoogleJsonWebSignature.Payload? payload = await VerifyGoogleIdToken(model.GoogleToken); if (payload == null) return Unauthorized(); User? user = await _dbContext.Users.SingleOrDefaultAsync(u => u.GoogleId == payload.Subject); if (user != null) { //Check if user's name changed and update if it did if (user.Name != payload.Name) user.Name = payload.Name; } else { user = new User() { Name = payload.Name, GoogleId = payload.Subject, Elements = new List() }; await _dbContext.Users.AddAsync(user); } await _dbContext.SaveChangesAsync(); List claims = new() { new Claim("id", user.Id.ToString()), new Claim(ClaimTypes.Role, "User") }; ClaimsIdentity claimsIdentity = new(claims, CookieAuthenticationDefaults.AuthenticationScheme); AuthenticationProperties authProperties = new() { IsPersistent = true, AllowRefresh = true }; await HttpContext.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties); var response = new { Id = user.Id.ToString() }; return Ok(JsonSerializer.Serialize(response)); } [HttpPost] public async Task Logout() { await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); return Ok(); } private async Task VerifyGoogleIdToken(string token) { try { GoogleJsonWebSignature.Payload? payload = await GoogleJsonWebSignature.ValidateAsync(token); return payload; } catch (InvalidJwtException) { return null; } } }