From 516ba5bb8ee15dbf9f63b3875c86fe4d52e0f517 Mon Sep 17 00:00:00 2001 From: nikita Date: Thu, 26 Dec 2024 16:14:55 +0300 Subject: [PATCH] feat: add a token handler --- ApiDto/Common/OAuthAction.cs | 17 ++++++ Endpoint/Controllers/V1/AuthController.cs | 64 ++++++++++++++++++++++- 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 ApiDto/Common/OAuthAction.cs diff --git a/ApiDto/Common/OAuthAction.cs b/ApiDto/Common/OAuthAction.cs new file mode 100644 index 0000000..1cc0908 --- /dev/null +++ b/ApiDto/Common/OAuthAction.cs @@ -0,0 +1,17 @@ +namespace Mirea.Api.Dto.Common; + +/// +/// Defines the actions that can be performed with an OAuth token. +/// +public enum OAuthAction +{ + /// + /// The action to log in the user using the provided OAuth token. + /// + Login, + + /// + /// The action to bind an OAuth provider to the user's account. + /// + Bind +} \ No newline at end of file diff --git a/Endpoint/Controllers/V1/AuthController.cs b/Endpoint/Controllers/V1/AuthController.cs index 640c80c..544533d 100644 --- a/Endpoint/Controllers/V1/AuthController.cs +++ b/Endpoint/Controllers/V1/AuthController.cs @@ -11,12 +11,13 @@ using Mirea.Api.Endpoint.Common.Exceptions; using Mirea.Api.Endpoint.Common.MapperDto; using Mirea.Api.Endpoint.Common.Services; using Mirea.Api.Endpoint.Configuration.Model; -using Mirea.Api.Security.Common.Model; using Mirea.Api.Security.Services; using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Diagnostics; using System.Linq; +using System.Security.Claims; using System.Threading.Tasks; using CookieOptions = Mirea.Api.Security.Common.Model.CookieOptions; using OAuthProvider = Mirea.Api.Security.Common.Domain.OAuthProvider; @@ -164,6 +165,67 @@ public class AuthController(IOptionsSnapshot user, IOptionsSnapshot + /// Processes the OAuth token + /// + /// The OAuth token used for authentication or binding. + /// The action to be performed: Login or Bind. + /// If return Ok. If return + [HttpGet("HandleToken")] + [MaintenanceModeIgnore] + [BadRequestResponse] + public async Task HandleToken([FromQuery][MinLength(2)] string token, [FromQuery] OAuthAction action) + { + var (oAuthUser, error, isSuccess, provider) = await oAuthService.GetOAuthUser(GetCookieParams(), HttpContext, token); + + if (!isSuccess || oAuthUser == null || provider == null) + throw new ControllerArgumentException(error ?? "Token processing error."); + + switch (action) + { + case OAuthAction.Login: + return Ok(await auth.LoginOAuthAsync(GetCookieParams(), HttpContext, user.Value.ConvertToSecurity(), oAuthUser, provider.Value)); + + case OAuthAction.Bind: + var userId = HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier); + var admin = user.Value; + + if (string.IsNullOrEmpty(userId) || !int.TryParse(userId, out var result) || result != 1) + return Unauthorized(new ProblemDetails + { + Type = "https://tools.ietf.org/html/rfc9110#section-15.5.2", + Title = "Unauthorized", + Status = StatusCodes.Status401Unauthorized, + Detail = "The user is not logged in to link accounts.", + Extensions = new Dictionary() + { + { "traceId", HttpContext.TraceIdentifier } + } + }); + + if (admin.OAuthProviders != null && admin.OAuthProviders.ContainsKey(provider.Value)) + return Conflict(new ProblemDetails + { + Type = "https://tools.ietf.org/html/rfc9110#section-15.5.10", + Title = "Conflict", + Status = StatusCodes.Status409Conflict, + Detail = "This OAuth provider is already associated with the account.", + Extensions = new Dictionary() + { + { "traceId", HttpContext.TraceIdentifier } + } + }); + + admin.OAuthProviders ??= []; + admin.OAuthProviders.Add(provider.Value, oAuthUser); + admin.SaveSetting(); + + return Ok(); + default: + throw new ControllerArgumentException("The action cannot be processed."); + } + } + /// /// Logs in a user using their username or email and password. ///