2025-10-11 11:33:46 +02:00
|
|
|
using BimAI.Domain.Entities;
|
|
|
|
|
using BimAI.Infrastructure.Data;
|
2025-07-19 22:50:38 +02:00
|
|
|
using Google.Apis.Auth;
|
|
|
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
|
|
2025-10-11 11:33:46 +02:00
|
|
|
namespace BimAI.API.Services;
|
2025-07-19 22:50:38 +02:00
|
|
|
|
2025-10-11 11:33:46 +02:00
|
|
|
public class GoogleAuthService(BimAIDbContext context, IConfiguration configuration, ILogger<GoogleAuthService> logger)
|
2025-07-19 22:50:38 +02:00
|
|
|
{
|
2025-10-11 11:33:46 +02:00
|
|
|
private readonly BimAIDbContext _context = context;
|
2025-07-19 22:50:38 +02:00
|
|
|
private readonly IConfiguration _configuration = configuration;
|
|
|
|
|
private readonly ILogger<GoogleAuthService> _logger = logger;
|
|
|
|
|
|
|
|
|
|
public async Task<(bool IsValid, User? user, string? error)> ValidateGoogleTokenAsync(string idToken)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var clientId = _configuration["GoogleAuth:ClientId"];
|
|
|
|
|
if (string.IsNullOrEmpty(clientId))
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError("Google Auth Client Id is not configured");
|
|
|
|
|
return (false, null, "Google Auth Client Id is not configured");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var payload = await GoogleJsonWebSignature.ValidateAsync(idToken,
|
|
|
|
|
new GoogleJsonWebSignature.ValidationSettings
|
|
|
|
|
{
|
|
|
|
|
Audience = new[] { clientId }
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
_logger.LogInformation("Google token validated for user: {Email}", payload.Email);
|
|
|
|
|
|
|
|
|
|
var user = await _context.Users
|
|
|
|
|
.FirstOrDefaultAsync(x => x.GoogleId == payload.Subject || x.Email == payload.Email);
|
|
|
|
|
|
|
|
|
|
if (user == null)
|
|
|
|
|
{
|
2025-10-11 11:33:46 +02:00
|
|
|
_logger.LogError("User not found in BimAI database: {Email}", payload.Email);
|
|
|
|
|
return (false, null, "User not found in BimAI database");
|
2025-07-19 22:50:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!user.IsActive)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError("User is not active: {Email}", payload.Email);
|
|
|
|
|
return (false, null, "User is not active");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
user.LastLoginAt = DateTime.UtcNow;
|
|
|
|
|
user.FullName = payload.Name;
|
|
|
|
|
|
|
|
|
|
if (user.GoogleId != payload.Subject)
|
|
|
|
|
{
|
|
|
|
|
user.GoogleId = payload.Subject;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await _context.SaveChangesAsync();
|
|
|
|
|
|
|
|
|
|
_logger.LogInformation("User logged in: {Email}", payload.Email);
|
|
|
|
|
|
|
|
|
|
return (true, user, null);
|
|
|
|
|
}
|
|
|
|
|
catch (InvalidJwtException ex)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError(ex, "Invalid JWT token");
|
|
|
|
|
return (false, null, "Invalid JWT token");
|
|
|
|
|
} catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError(ex, "Error validating Google token");
|
|
|
|
|
return (false, null, "Error validating Google token");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|