using System.Security.Claims; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using TaxBaik.Application.Services; using TaxBaik.Web.Services; namespace TaxBaik.Web.Pages.Portal; public class ExternalCallbackModel : PageModel { private readonly PortalUserService _portalUserService; private readonly ClientService _clientService; public ExternalCallbackModel(PortalUserService portalUserService, ClientService clientService) { _portalUserService = portalUserService; _clientService = clientService; } public async Task OnGetAsync(string provider) { var external = await HttpContext.AuthenticateAsync(PortalOAuthDefaults.ExternalScheme); if (external?.Principal is null) return RedirectToPage("/Portal/Login"); var email = external.Principal.FindFirstValue(ClaimTypes.Email); var name = external.Principal.FindFirstValue(ClaimTypes.Name) ?? "고객"; var providerId = external.Principal.FindFirstValue(ClaimTypes.NameIdentifier) ?? ""; if (string.IsNullOrWhiteSpace(providerId)) return RedirectToPage("/Portal/Login"); var existing = await _portalUserService.GetByProviderAsync(provider, providerId); if (existing is null && !string.IsNullOrWhiteSpace(email)) { existing = await _portalUserService.GetByEmailAsync(email); if (existing is null) { int? clientId = null; var linkedClient = await _clientService.GetByEmailAsync(email); if (linkedClient is null && !string.IsNullOrWhiteSpace(external.Principal.FindFirstValue("phone"))) linkedClient = await _clientService.GetByPhoneAsync(external.Principal.FindFirstValue("phone")!); if (linkedClient is not null) clientId = linkedClient.Id; await _portalUserService.RegisterOAuthAsync( name, email, external.Principal.FindFirstValue("phone") ?? "", provider, providerId, clientId); existing = await _portalUserService.GetByEmailAsync(email); } else if (!string.Equals(existing.Provider, provider, StringComparison.OrdinalIgnoreCase) || !string.Equals(existing.ProviderId, providerId, StringComparison.OrdinalIgnoreCase)) { await _portalUserService.LinkOAuthAsync(existing, provider, providerId, name, email); } } if (existing is not null && !existing.ClientId.HasValue && !string.IsNullOrWhiteSpace(email)) { var linkedClient = await _clientService.GetByEmailAsync(email); if (linkedClient is null && !string.IsNullOrWhiteSpace(external.Principal.FindFirstValue("phone"))) linkedClient = await _clientService.GetByPhoneAsync(external.Principal.FindFirstValue("phone")!); if (linkedClient is not null) { await _portalUserService.AttachClientAsync(existing, linkedClient.Id); existing.ClientId = linkedClient.Id; } } if (existing is null) return RedirectToPage("/Portal/Login"); var claims = new List { new(ClaimTypes.NameIdentifier, existing.Id.ToString()), new(ClaimTypes.Name, existing.Name), new(ClaimTypes.Email, existing.Email), new("portal_user_id", existing.Id.ToString()) }; if (existing.ClientId.HasValue) claims.Add(new("client_id", existing.ClientId.Value.ToString())); await HttpContext.SignInAsync( PortalAuthDefaults.Scheme, new ClaimsPrincipal(new ClaimsIdentity(claims, PortalAuthDefaults.Scheme)), new AuthenticationProperties { IsPersistent = true }); await HttpContext.SignOutAsync(PortalOAuthDefaults.ExternalScheme); return RedirectToPage("/Portal/Index"); } }