using System.Net.Http.Json; using System.Text.Json; using eprintServer.Models; using eprintServer.Entities; using eprintServer.Enums; namespace eprintServer.Services; public class GoogleOAuthService : BaseOAuthService { private readonly OAuthSettingsService _settingsService; private readonly IHttpClientFactory _httpClientFactory; public GoogleOAuthService(OAuthSettingsService settingsService, UserService userService, TokenService tokenService, IHttpClientFactory httpClientFactory) : base(userService, tokenService) { _settingsService = settingsService; _httpClientFactory = httpClientFactory; } public async Task<(User? user, string? token, string? error)> HandleLoginCallbackAsync(string code) { var settings = await _settingsService.GetOrCreateSettingsAsync(); var client = _httpClientFactory.CreateClient(); // 1. Exchange Code for Access Token var tokenResponse = await client.PostAsync("https://oauth2.googleapis.com/token", new FormUrlEncodedContent(new Dictionary { ["code"] = code, ["client_id"] = settings.GoogleClientId!, ["client_secret"] = settings.GoogleClientSecret!, ["redirect_uri"] = "https://server.etbaaonline.com/api/v1/oauth/google/callback", // Must match your front-end config ["grant_type"] = "authorization_code" })); if (!tokenResponse.IsSuccessStatusCode) return (null, null, "Google code exchange failed."); var tokenData = await tokenResponse.Content.ReadFromJsonAsync(); var accessToken = tokenData.GetProperty("access_token").GetString(); // 2. Get User Info client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken); var userResponse = await client.GetAsync("https://www.googleapis.com/oauth2/v2/userinfo"); var googleUser = await userResponse.Content.ReadFromJsonAsync(); var externalUser = new ExternalUserData { Email = googleUser.GetProperty("email").GetString()!, Name = googleUser.GetProperty("name").GetString()!, ProviderUserId = googleUser.GetProperty("id").GetString() }; return await SignInUserAsync(externalUser, Provider.GOOGLE); } }