diff --git a/Endpoint/Controllers/V1/AuthController.cs b/Endpoint/Controllers/V1/AuthController.cs index 3946c56..9b199fc 100644 --- a/Endpoint/Controllers/V1/AuthController.cs +++ b/Endpoint/Controllers/V1/AuthController.cs @@ -15,7 +15,9 @@ using Mirea.Api.Security.Common.Domain; using Mirea.Api.Security.Services; using System; using System.Collections.Generic; +using System.Security.Claims; using System.Threading.Tasks; +using OAuthProvider = Mirea.Api.Security.Common.Domain.OAuthProvider; namespace Mirea.Api.Endpoint.Controllers.V1; @@ -30,13 +32,36 @@ public class AuthController(IOptionsSnapshot user, AuthService auth, Pass }; /// - /// Gets the list of available OAuth providers with their respective redirect URIs. + /// Initiates the OAuth2 authorization process for the selected provider. /// - /// A list of available providers. - [HttpGet("GetAvailableProviders")] - public ActionResult> GetUrls() => + /// + /// This method generates a redirect URL for the selected provider and redirects the user to it. + /// + /// The identifier of the OAuth provider to authorize with. + /// A redirect to the OAuth provider's authorization URL. + /// Thrown if the specified provider is not valid. + [HttpGet("AuthorizeOAuth2")] + [MaintenanceModeIgnore] + public ActionResult AuthorizeOAuth2([FromQuery] int provider) + { + if (!Enum.IsDefined(typeof(OAuthProvider), provider)) + throw new ControllerArgumentException("There is no selected provider"); + + return Redirect(oAuthService.GetProviderRedirect(HttpContext, GetCookieParams(), HttpContext.GetApiUrl(Url.Action("OAuth2")!), (OAuthProvider)provider).AbsoluteUri); + } + + /// + /// Retrieves a list of available OAuth providers with their corresponding authorization URLs. + /// + /// + /// This allows the client to fetch all possible OAuth options and the URLs required to initiate authorization. + /// + /// A list of available providers and their redirect URLs. + [HttpGet("AvailableProviders")] + [MaintenanceModeIgnore] + public ActionResult> AvailableProviders() => Ok(oAuthService - .GetAvailableProviders(HttpContext, GetCookieParams(), HttpContext.GetApiUrl(Url.Action("OAuth2")!)) + .GetAvailableProviders(HttpContext, HttpContext.GetApiUrl(Url.Action("AuthorizeOAuth2")!)) .ConvertToDto()); /// diff --git a/Security/Services/OAuthService.cs b/Security/Services/OAuthService.cs index 7721b86..b23d9da 100644 --- a/Security/Services/OAuthService.cs +++ b/Security/Services/OAuthService.cs @@ -97,20 +97,26 @@ public class OAuthService(ILogger logger, Dictionary (x.Key, new Uri(ProviderData[x.Key].RedirectUrl.TrimEnd('/') + - string.Format(redirectUri, - x.Value.ClientId, - ProviderData[x.Key].Scope, - Enum.GetName(x.Key)))) - ).ToArray(); + public Uri GetProviderRedirect(HttpContext context, CookieOptionsParameters cookieOptions, string redirectUri, OAuthProvider provider) + { + var providerData = providers[provider]; + + var redirectUrl = $"?client_id={providerData.ClientId}" + + "&response_type=code" + + $"&redirect_uri={redirectUri}" + + $"&scope={ProviderData[provider].Scope}" + + $"&state={new RequestContextInfo(context, cookieOptions).Fingerprint}_{Enum.GetName(provider)}"; + + + + return new Uri(ProviderData[provider].RedirectUrl + redirectUrl); + } + + public (OAuthProvider Provider, Uri Redirect)[] GetAvailableProviders(HttpContext context, string redirectUri) + { + return providers.Select(x => (x.Key, new Uri(redirectUri.TrimEnd('/') + "/?provider=" + (int)x.Key))) + .ToArray(); } public async Task<(OAuthProvider provider, OAuthUser User)> LoginOAuth(HttpContext context, CookieOptionsParameters cookieOptions, string redirectUrl, string code, string state, CancellationToken cancellation = default)