using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using PlaylistShared.Api.Entities; using PlaylistShared.Api.Services; using System.Security.Claims; namespace PlaylistShared.Api.Controllers; [ApiController] [Route("api/[controller]")] public class OpenIdController : ControllerBase { private readonly SignInManager _signInManager; private readonly UserManager _userManager; private readonly JwtService _jwtService; private readonly IConfiguration _configuration; public OpenIdController( SignInManager signInManager, UserManager userManager, JwtService jwtService, IConfiguration configuration) { _signInManager = signInManager; _userManager = userManager; _jwtService = jwtService; _configuration = configuration; } [HttpGet("login")] public IActionResult Login(string? returnUrl = null) { var redirectUrl = Url.Action(nameof(Callback), "OpenId", new { returnUrl }); var properties = _signInManager.ConfigureExternalAuthenticationProperties("Keycloak", redirectUrl); return Challenge(properties, "Keycloak"); } [HttpGet("callback")] public async Task Callback(string? returnUrl = null, string? remoteError = null) { if (remoteError != null) return BadRequest($"Ошибка внешнего входа: {remoteError}"); var info = await _signInManager.GetExternalLoginInfoAsync(); if (info == null) return BadRequest("Не удалось получить информацию от провайдера"); var email = info.Principal.FindFirst(ClaimTypes.Email)?.Value; var userName = info.Principal.FindFirst(ClaimTypes.Name)?.Value ?? email; var user = await _userManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey); if (user == null) { user = await _userManager.FindByEmailAsync(email); if (user == null) { user = new ApplicationUser { UserName = userName, Email = email }; var createResult = await _userManager.CreateAsync(user); if (!createResult.Succeeded) return BadRequest(createResult.Errors); } var loginResult = await _userManager.AddLoginAsync(user, info); if (!loginResult.Succeeded) return BadRequest(loginResult.Errors); } await _signInManager.SignInAsync(user, isPersistent: false); var (token, refreshToken, _) = await _jwtService.GenerateTokenAsync(user); return Redirect($"{_configuration["Client:BaseUrl"]}/auth-callback?token={token}&refreshToken={refreshToken}"); } }