feat: add a method for getting data from OAuth
All checks were successful
.NET Test Pipeline / build-and-test (push) Successful in 2m20s
Build and Deploy Docker Container / build-and-deploy (push) Successful in 1m24s

This commit is contained in:
Polianin Nikita 2024-12-18 07:40:07 +03:00
parent e9ff1cabe8
commit 5cc54eac44

View File

@ -22,7 +22,7 @@ using OAuthProvider = Mirea.Api.Security.Common.Domain.OAuthProvider;
namespace Mirea.Api.Endpoint.Controllers.V1; namespace Mirea.Api.Endpoint.Controllers.V1;
[ApiVersion("1.0")] [ApiVersion("1.0")]
public class AuthController(IOptionsSnapshot<Admin> user, AuthService auth, PasswordHashService passwordService) : BaseController public class AuthController(IOptionsSnapshot<Admin> user, IOptionsSnapshot<GeneralConfig> generalConfig, AuthService auth, PasswordHashService passwordService, OAuthService oAuthService) : BaseController
{ {
private CookieOptionsParameters GetCookieParams() => private CookieOptionsParameters GetCookieParams() =>
new() new()
@ -31,6 +31,95 @@ public class AuthController(IOptionsSnapshot<Admin> user, AuthService auth, Pass
Path = UrlHelper.GetSubPathWithoutFirstApiName + "api" Path = UrlHelper.GetSubPathWithoutFirstApiName + "api"
}; };
private static string GenerateHtmlResponse(string title, string message, OAuthProvider? provider, bool isError = false)
{
string messageColor = isError ? "red" : "white";
string script = "<script>setTimeout(()=>{if(window.opener){window.opener.postMessage(" +
"{success:" + !isError +
",provider:'" + (provider == null ? "null" : (int)provider) +
"',providerName:'" + (provider == null ? "null" : Enum.GetName(provider.Value)) +
"',message:'" + message.Replace("'", "\\'") +
"'},'*');}window.close();}, 5000);</script>";
return $"<!DOCTYPE html><html lang=ru><head><meta charset=UTF-8><meta content=\"width=device-width,initial-scale=1\"name=viewport><link href=\"https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap\"rel=stylesheet><style>body{{background-color:#121212;color:#fff;font-family:Roboto,sans-serif;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;text-align:center}}.container{{max-width:600px;padding:20px;border-radius:8px;background-color:#1e1e1e;box-shadow:0 4px 20px rgba(0,0,0,.5)}}h1{{font-size:24px;margin-bottom:20px}}p{{font-size:16px;color:{messageColor}}}</style><title>{title}</title></head><body><div class=container><h1>{title}</h1><p>{message}<p style=font-size:14px;color:silver;>Это информационная страница. Вы можете закрыть её.</div>{script}</body></html>";
}
[HttpGet("OAuth2")]
[BadRequestResponse]
[ProducesResponseType(typeof(string), StatusCodes.Status200OK)]
[Produces("text/html")]
[MaintenanceModeIgnore]
public async Task<ContentResult> OAuth2([FromQuery] string code, [FromQuery] string state)
{
var userId = HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
string title;
string message;
OAuthProvider provider;
OAuthUser oAuthUser;
try
{
(provider, oAuthUser) = await oAuthService.LoginOAuth(HttpContext, GetCookieParams(),
HttpContext.GetApiUrl(Url.Action("OAuth2")!), code, state);
}
catch (Exception e)
{
title = "Произошла ошибка при общении с провайдером OAuth!";
message = e.Message;
return Content(GenerateHtmlResponse(title, message, null, true), "text/html");
}
var userEntity = user.Value;
if (userId != null)
{
userEntity.OAuthProviders ??= new Dictionary<OAuthProvider, OAuthUser>();
if (!userEntity.OAuthProviders.TryAdd(provider, oAuthUser))
{
title = "Ошибка связи аккаунта!";
message = "Этот OAuth провайдер уже связан с вашей учетной записью. Пожалуйста, используйте другого провайдера или удалите связь с аккаунтом.";
return Content(GenerateHtmlResponse(title, message, provider, true), "text/html");
}
userEntity.SaveSetting();
title = "Учетная запись успешно связана.";
message = "Вы успешно связали свою учетную запись с провайдером OAuth. Вы можете продолжить использовать приложение.";
return Content(GenerateHtmlResponse(title, message, provider), "text/html");
}
if (userEntity.OAuthProviders != null &&
userEntity.OAuthProviders.TryGetValue(provider, out var userOAuth) &&
userOAuth.Id == oAuthUser.Id)
{
await auth.LoginOAuthAsync(GetCookieParams(), HttpContext, new User
{
Id = 1.ToString(),
Username = userEntity.Username,
Email = userEntity.Email,
PasswordHash = userEntity.PasswordHash,
Salt = userEntity.Salt,
TwoFactorAuthenticator = userEntity.TwoFactorAuthenticator,
SecondFactorToken = userEntity.Secret,
OAuthProviders = userEntity.OAuthProviders
}, provider);
title = "Успешный вход в аккаунт.";
message = "Вы успешно вошли в свою учетную запись. Добро пожаловать!";
return Content(GenerateHtmlResponse(title, message, provider), "text/html");
}
title = "Вы успешно зарегистрированы.";
message = "Процесс завершен. Вы можете закрыть эту страницу.";
userEntity.Email = string.IsNullOrEmpty(oAuthUser.Email) ? string.Empty : oAuthUser.Email;
userEntity.Username = string.IsNullOrEmpty(oAuthUser.Username) ? string.Empty : oAuthUser.Username;
userEntity.OAuthProviders ??= [];
userEntity.OAuthProviders.Add(provider, oAuthUser);
userEntity.SaveSetting();
return Content(GenerateHtmlResponse(title, message, provider), "text/html");
}
/// <summary> /// <summary>
/// Initiates the OAuth2 authorization process for the selected provider. /// Initiates the OAuth2 authorization process for the selected provider.
/// </summary> /// </summary>