refactor: distribute the domain folder

This commit is contained in:
nikita 2024-12-26 13:38:43 +03:00
parent 43edab2912
commit 36026b3afb
22 changed files with 98 additions and 67 deletions

View File

@ -1,17 +1,17 @@
using Mirea.Api.Dto.Common; using PasswordPolicy = Mirea.Api.Dto.Common.PasswordPolicy;
namespace Mirea.Api.Endpoint.Common.MapperDto; namespace Mirea.Api.Endpoint.Common.MapperDto;
public static class PasswordPolicyConverter public static class PasswordPolicyConverter
{ {
public static Security.Common.Domain.PasswordPolicy ConvertFromDto(this PasswordPolicy policy) => public static Security.Common.Model.PasswordPolicy ConvertFromDto(this PasswordPolicy policy) =>
new(policy.MinimumLength, new(policy.MinimumLength,
policy.RequireLetter, policy.RequireLetter,
policy.RequireLettersDifferentCase, policy.RequireLettersDifferentCase,
policy.RequireDigit, policy.RequireDigit,
policy.RequireSpecialCharacter); policy.RequireSpecialCharacter);
public static PasswordPolicy ConvertToDto(this Security.Common.Domain.PasswordPolicy policy) => public static PasswordPolicy ConvertToDto(this Security.Common.Model.PasswordPolicy policy) =>
new() new()
{ {
MinimumLength = policy.MinimumLength, MinimumLength = policy.MinimumLength,

View File

@ -1,24 +1,23 @@
using Mirea.Api.Dto.Common; using Mirea.Api.Dto.Common;
using Mirea.Api.Security.Common.Domain;
using System; using System;
namespace Mirea.Api.Endpoint.Common.MapperDto; namespace Mirea.Api.Endpoint.Common.MapperDto;
public static class TwoFactorAuthenticationConverter public static class TwoFactorAuthenticationConverter
{ {
public static TwoFactorAuthentication ConvertToDto(this TwoFactorAuthenticator authenticator) => public static TwoFactorAuthentication ConvertToDto(this Security.Common.Model.TwoFactorAuthenticator authenticator) =>
authenticator switch authenticator switch
{ {
TwoFactorAuthenticator.None => TwoFactorAuthentication.None, Security.Common.Model.TwoFactorAuthenticator.None => TwoFactorAuthentication.None,
TwoFactorAuthenticator.Totp => TwoFactorAuthentication.TotpRequired, Security.Common.Model.TwoFactorAuthenticator.Totp => TwoFactorAuthentication.TotpRequired,
_ => throw new ArgumentOutOfRangeException(nameof(authenticator), authenticator, null) _ => throw new ArgumentOutOfRangeException(nameof(authenticator), authenticator, null)
}; };
public static TwoFactorAuthenticator ConvertFromDto(this TwoFactorAuthentication authentication) => public static Security.Common.Model.TwoFactorAuthenticator ConvertFromDto(this TwoFactorAuthentication authentication) =>
authentication switch authentication switch
{ {
TwoFactorAuthentication.None => TwoFactorAuthenticator.None, TwoFactorAuthentication.None => Security.Common.Model.TwoFactorAuthenticator.None,
TwoFactorAuthentication.TotpRequired => TwoFactorAuthenticator.Totp, TwoFactorAuthentication.TotpRequired => Security.Common.Model.TwoFactorAuthenticator.Totp,
_ => throw new ArgumentOutOfRangeException(nameof(authentication), authentication, null) _ => throw new ArgumentOutOfRangeException(nameof(authentication), authentication, null)
}; };
} }

View File

@ -1,5 +1,6 @@
using Mirea.Api.Endpoint.Common.Services; using Mirea.Api.Endpoint.Common.Services;
using Mirea.Api.Security.Common.Domain; using Mirea.Api.Security.Common.Domain;
using Mirea.Api.Security.Common.Model;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text.Json; using System.Text.Json;

View File

@ -1,6 +1,6 @@
using Mirea.Api.Endpoint.Common.Services; using Mirea.Api.Endpoint.Common.Services;
using Mirea.Api.Endpoint.Configuration.Model.GeneralSettings; using Mirea.Api.Endpoint.Configuration.Model.GeneralSettings;
using Mirea.Api.Security.Common.Domain; using Mirea.Api.Security.Common.Model;
using System.IO; using System.IO;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;

View File

@ -18,7 +18,7 @@ using Mirea.Api.Endpoint.Common.Services;
using Mirea.Api.Endpoint.Configuration.Model; using Mirea.Api.Endpoint.Configuration.Model;
using Mirea.Api.Endpoint.Configuration.Model.GeneralSettings; using Mirea.Api.Endpoint.Configuration.Model.GeneralSettings;
using Mirea.Api.Endpoint.Configuration.Validation.Validators; using Mirea.Api.Endpoint.Configuration.Validation.Validators;
using Mirea.Api.Security.Common.Domain; using Mirea.Api.Security.Common.Model;
using Mirea.Api.Security.Services; using Mirea.Api.Security.Services;
using MySqlConnector; using MySqlConnector;
using Npgsql; using Npgsql;
@ -32,6 +32,7 @@ using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security; using System.Security;
using System.Security.Cryptography; using System.Security.Cryptography;
using CookieOptions = Microsoft.AspNetCore.Http.CookieOptions;
using PasswordPolicy = Mirea.Api.Dto.Common.PasswordPolicy; using PasswordPolicy = Mirea.Api.Dto.Common.PasswordPolicy;
namespace Mirea.Api.Endpoint.Controllers.Configuration; namespace Mirea.Api.Endpoint.Controllers.Configuration;
@ -539,7 +540,7 @@ public class SetupController(
[TokenAuthentication] [TokenAuthentication]
public ActionResult<bool> SetPasswordPolicy([FromBody] PasswordPolicy? policy = null) public ActionResult<bool> SetPasswordPolicy([FromBody] PasswordPolicy? policy = null)
{ {
GeneralConfig.PasswordPolicy = policy?.ConvertFromDto() ?? new Security.Common.Domain.PasswordPolicy(); GeneralConfig.PasswordPolicy = policy?.ConvertFromDto() ?? new Security.Common.Model.PasswordPolicy();
cache.Set("password", true); cache.Set("password", true);
return true; return true;
} }

View File

@ -11,13 +11,14 @@ using Mirea.Api.Endpoint.Common.Exceptions;
using Mirea.Api.Endpoint.Common.MapperDto; using Mirea.Api.Endpoint.Common.MapperDto;
using Mirea.Api.Endpoint.Common.Services; using Mirea.Api.Endpoint.Common.Services;
using Mirea.Api.Endpoint.Configuration.Model; using Mirea.Api.Endpoint.Configuration.Model;
using Mirea.Api.Security.Common.Domain; using Mirea.Api.Security.Common.Model;
using Mirea.Api.Security.Services; using Mirea.Api.Security.Services;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using CookieOptions = Mirea.Api.Security.Common.Model.CookieOptions;
using OAuthProvider = Mirea.Api.Security.Common.Domain.OAuthProvider; using OAuthProvider = Mirea.Api.Security.Common.Domain.OAuthProvider;
namespace Mirea.Api.Endpoint.Controllers.V1; namespace Mirea.Api.Endpoint.Controllers.V1;
@ -26,7 +27,7 @@ namespace Mirea.Api.Endpoint.Controllers.V1;
public class AuthController(IOptionsSnapshot<Admin> user, IOptionsSnapshot<GeneralConfig> generalConfig, AuthService auth, public class AuthController(IOptionsSnapshot<Admin> user, IOptionsSnapshot<GeneralConfig> generalConfig, AuthService auth,
PasswordHashService passwordService, OAuthService oAuthService) : BaseController PasswordHashService passwordService, OAuthService oAuthService) : BaseController
{ {
private CookieOptionsParameters GetCookieParams() => private CookieOptions GetCookieParams() =>
new() new()
{ {
Domain = HttpContext.GetCurrentDomain(), Domain = HttpContext.GetCurrentDomain(),
@ -53,6 +54,19 @@ public class AuthController(IOptionsSnapshot<Admin> user, IOptionsSnapshot<Gener
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}}</style><title>{title}</title></head><body><div class=container><h1>{title}</h1>{blockInfo}<p style=font-size:14px;color:silver;>{message}</p><code style=font-size:12px;color:gray;>TraceId={traceId}</code></div>{script}</body></html>"; 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}}</style><title>{title}</title></head><body><div class=container><h1>{title}</h1>{blockInfo}<p style=font-size:14px;color:silver;>{message}</p><code style=font-size:12px;color:gray;>TraceId={traceId}</code></div>{script}</body></html>";
} }
/// <summary>
/// Handles the callback from an OAuth2 provider and finalizes the authorization process.
/// </summary>
/// <remarks>
/// This method processes the response from an OAuth provider after the user authorizes the application.
/// Upon successful authorization, it redirects the user back to the specified callback URL.
/// </remarks>
/// <param name="code">The authorization code returned by the OAuth provider.</param>
/// <param name="state">The state parameter to ensure the request's integrity and prevent CSRF attacks.</param>
/// <returns>
/// An HTML response indicating the success or failure of the authorization process.
/// If a callback URL is provided, the user will be redirected to it.
/// </returns>
[HttpGet("OAuth2")] [HttpGet("OAuth2")]
[BadRequestResponse] [BadRequestResponse]
[Produces("text/html")] [Produces("text/html")]
@ -163,6 +177,7 @@ public class AuthController(IOptionsSnapshot<Admin> user, IOptionsSnapshot<Gener
var tokenResult = await auth.LoginAsync( var tokenResult = await auth.LoginAsync(
GetCookieParams(), GetCookieParams(),
HttpContext,
new User new User
{ {
Id = 1.ToString(), Id = 1.ToString(),
@ -174,7 +189,7 @@ public class AuthController(IOptionsSnapshot<Admin> user, IOptionsSnapshot<Gener
SecondFactorToken = userEntity.Secret, SecondFactorToken = userEntity.Secret,
OAuthProviders = userEntity.OAuthProviders OAuthProviders = userEntity.OAuthProviders
}, },
HttpContext, request.Password, request.Username); request.Password, request.Username);
return Ok(tokenResult.ConvertToDto()); return Ok(tokenResult.ConvertToDto());
} }

View File

@ -1,4 +1,6 @@
namespace Mirea.Api.Security.Common.Domain.Caching; using Mirea.Api.Security.Common.Model;
namespace Mirea.Api.Security.Common.Domain.Caching;
internal class FirstAuthToken internal class FirstAuthToken
{ {

View File

@ -1,6 +1,6 @@
namespace Mirea.Api.Security.Common.Domain.OAuth2; namespace Mirea.Api.Security.Common.Domain;
public class OAuthPayload internal class OAuthPayload
{ {
public required OAuthProvider Provider { get; set; } public required OAuthProvider Provider { get; set; }
public required string Callback { get; set; } public required string Callback { get; set; }

View File

@ -1,6 +1,6 @@
using System; using System;
namespace Mirea.Api.Security.Common.Domain.OAuth2; namespace Mirea.Api.Security.Common.Domain;
internal readonly struct OAuthProviderUrisData internal readonly struct OAuthProviderUrisData
{ {

View File

@ -7,7 +7,7 @@ namespace Mirea.Api.Security.Common.Domain;
internal class RequestContextInfo internal class RequestContextInfo
{ {
public RequestContextInfo(HttpContext context, CookieOptionsParameters cookieOptions) public RequestContextInfo(HttpContext context, Model.CookieOptions cookieOptions)
{ {
var ipEntity = context.Connection.RemoteIpAddress; var ipEntity = context.Connection.RemoteIpAddress;

View File

@ -1,16 +1,16 @@
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using System; using System;
namespace Mirea.Api.Security.Common.Domain; namespace Mirea.Api.Security.Common.Model;
public class CookieOptionsParameters public class CookieOptions
{ {
public required string Domain { get; set; } public required string Domain { get; set; }
public required string Path { get; set; } public required string Path { get; set; }
internal void SetCookie(HttpContext context, string name, string value, DateTimeOffset? expires = null) internal void SetCookie(HttpContext context, string name, string value, DateTimeOffset? expires = null)
{ {
var cookieOptions = new CookieOptions var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions
{ {
Expires = expires, Expires = expires,
Path = Path, Path = Path,

View File

@ -1,4 +1,4 @@
namespace Mirea.Api.Security.Common.Domain; namespace Mirea.Api.Security.Common.Model;
public class PasswordPolicy( public class PasswordPolicy(
int minimumLength = 8, int minimumLength = 8,

View File

@ -1,4 +1,4 @@
namespace Mirea.Api.Security.Common.Domain; namespace Mirea.Api.Security.Common.Model;
public enum TwoFactorAuthenticator public enum TwoFactorAuthenticator
{ {

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using Mirea.Api.Security.Common.Domain;
using System.Collections.Generic;
namespace Mirea.Api.Security.Common.Domain; namespace Mirea.Api.Security.Common.Model;
public class User public class User
{ {

View File

@ -1,8 +1,8 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Mirea.Api.Security.Common.Domain.OAuth2; namespace Mirea.Api.Security.Common.OAuth2;
public class OAuthTokenResponse internal class OAuthTokenResponse
{ {
[JsonPropertyName("access_token")] [JsonPropertyName("access_token")]
public required string AccessToken { get; set; } public required string AccessToken { get; set; }

View File

@ -1,7 +1,8 @@
using Mirea.Api.Security.Common.Interfaces; using Mirea.Api.Security.Common.Domain;
using Mirea.Api.Security.Common.Interfaces;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Mirea.Api.Security.Common.Domain.OAuth2.UserInfo; namespace Mirea.Api.Security.Common.OAuth2.UserInfo;
internal class GoogleUserInfo : IUserInfo internal class GoogleUserInfo : IUserInfo
{ {

View File

@ -1,7 +1,8 @@
using Mirea.Api.Security.Common.Interfaces; using Mirea.Api.Security.Common.Domain;
using Mirea.Api.Security.Common.Interfaces;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Mirea.Api.Security.Common.Domain.OAuth2.UserInfo; namespace Mirea.Api.Security.Common.OAuth2.UserInfo;
internal class MailRuUserInfo : IUserInfo internal class MailRuUserInfo : IUserInfo
{ {

View File

@ -1,7 +1,8 @@
using Mirea.Api.Security.Common.Interfaces; using Mirea.Api.Security.Common.Domain;
using Mirea.Api.Security.Common.Interfaces;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Mirea.Api.Security.Common.Domain.OAuth2.UserInfo; namespace Mirea.Api.Security.Common.OAuth2.UserInfo;
internal class YandexUserInfo : IUserInfo internal class YandexUserInfo : IUserInfo
{ {

View File

@ -1,8 +1,8 @@
using System; using System;
namespace Mirea.Api.Security.Common.Domain; namespace Mirea.Api.Security.Common.ViewModel;
public class LoginOAuthResult public class LoginOAuth
{ {
public bool Success { get; set; } public bool Success { get; set; }
public required string Token { get; set; } public required string Token { get; set; }

View File

@ -4,11 +4,13 @@ using Mirea.Api.Security.Common;
using Mirea.Api.Security.Common.Domain; using Mirea.Api.Security.Common.Domain;
using Mirea.Api.Security.Common.Domain.Caching; using Mirea.Api.Security.Common.Domain.Caching;
using Mirea.Api.Security.Common.Interfaces; using Mirea.Api.Security.Common.Interfaces;
using Mirea.Api.Security.Common.Model;
using System; using System;
using System.Security; using System.Security;
using System.Text.Json; using System.Text.Json;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using CookieOptions = Mirea.Api.Security.Common.Model.CookieOptions;
namespace Mirea.Api.Security.Services; namespace Mirea.Api.Security.Services;
@ -94,7 +96,7 @@ public class AuthService(ICacheService cache, IAccessToken accessTokenService, I
throw new SecurityException("Authentication failed. Please check your credentials."); throw new SecurityException("Authentication failed. Please check your credentials.");
} }
private async Task GenerateAuthTokensAsync(CookieOptionsParameters cookieOptions, HttpContext context, private async Task GenerateAuthTokensAsync(CookieOptions cookieOptions, HttpContext context,
RequestContextInfo requestContext, string userId, CancellationToken cancellation = default) RequestContextInfo requestContext, string userId, CancellationToken cancellation = default)
{ {
var refreshToken = GenerateRefreshToken(); var refreshToken = GenerateRefreshToken();
@ -118,23 +120,7 @@ public class AuthService(ICacheService cache, IAccessToken accessTokenService, I
authToken.Fingerprint); authToken.Fingerprint);
} }
public async Task<TwoFactorAuthenticator> LoginOAuthAsync(CookieOptionsParameters cookieOptions, HttpContext context, User user, public async Task<bool> LoginAsync(CookieOptions cookieOptions, HttpContext context, TwoFactorAuthenticator authenticator, string code,
CancellationToken cancellation = default)
{
var requestContext = new RequestContextInfo(context, cookieOptions);
if (user.TwoFactorAuthenticator == TwoFactorAuthenticator.None)
{
await GenerateAuthTokensAsync(cookieOptions, context, requestContext, user.Id, cancellation);
return TwoFactorAuthenticator.None;
}
await StoreFirstAuthTokenInCache(user, requestContext, cancellation);
return user.TwoFactorAuthenticator;
}
public async Task<bool> LoginAsync(CookieOptionsParameters cookieOptions, HttpContext context, TwoFactorAuthenticator authenticator, string code,
CancellationToken cancellation = default) CancellationToken cancellation = default)
{ {
var requestContext = new RequestContextInfo(context, cookieOptions); var requestContext = new RequestContextInfo(context, cookieOptions);
@ -176,12 +162,12 @@ public class AuthService(ICacheService cache, IAccessToken accessTokenService, I
return true; return true;
} }
public async Task<TwoFactorAuthenticator> LoginAsync(CookieOptionsParameters cookieOptions, User user, HttpContext context, string password, private async Task<TwoFactorAuthenticator> LoginAsync(CookieOptions cookieOptions,
string username, CancellationToken cancellation = default) HttpContext context,
User user,
CancellationToken cancellation = default)
{ {
var requestContext = new RequestContextInfo(context, cookieOptions); var requestContext = new RequestContextInfo(context, cookieOptions);
username = username.Trim();
await VerifyUserOrThrowError(requestContext, user, password, username, cancellation);
if (user.TwoFactorAuthenticator == TwoFactorAuthenticator.None) if (user.TwoFactorAuthenticator == TwoFactorAuthenticator.None)
{ {
@ -194,7 +180,27 @@ public class AuthService(ICacheService cache, IAccessToken accessTokenService, I
return user.TwoFactorAuthenticator; return user.TwoFactorAuthenticator;
} }
public async Task RefreshTokenAsync(CookieOptionsParameters cookieOptions, HttpContext context, CancellationToken cancellation = default) public Task<TwoFactorAuthenticator> LoginOAuthAsync(CookieOptions cookieOptions,
HttpContext context,
User user,
CancellationToken cancellation = default) =>
LoginAsync(cookieOptions, context, user, cancellation);
public async Task<TwoFactorAuthenticator> LoginAsync(CookieOptions cookieOptions,
HttpContext context,
User user,
string password,
string username,
CancellationToken cancellation = default)
{
var requestContext = new RequestContextInfo(context, cookieOptions);
username = username.Trim();
await VerifyUserOrThrowError(requestContext, user, password, username, cancellation);
return await LoginAsync(cookieOptions, context, user, cancellation);
}
public async Task RefreshTokenAsync(CookieOptions cookieOptions, HttpContext context, CancellationToken cancellation = default)
{ {
const string defaultMessageError = "The session time has expired"; const string defaultMessageError = "The session time has expired";
var requestContext = new RequestContextInfo(context, cookieOptions); var requestContext = new RequestContextInfo(context, cookieOptions);
@ -271,7 +277,7 @@ public class AuthService(ICacheService cache, IAccessToken accessTokenService, I
cookieOptions.SetCookie(context, CookieNames.RefreshToken, authToken.RefreshToken, DateTime.UtcNow.Add(Lifetime)); cookieOptions.SetCookie(context, CookieNames.RefreshToken, authToken.RefreshToken, DateTime.UtcNow.Add(Lifetime));
} }
public async Task LogoutAsync(CookieOptionsParameters cookieOptions, HttpContext context, CancellationToken cancellation = default) public async Task LogoutAsync(CookieOptions cookieOptions, HttpContext context, CancellationToken cancellation = default)
{ {
var requestContext = new RequestContextInfo(context, cookieOptions); var requestContext = new RequestContextInfo(context, cookieOptions);

View File

@ -1,9 +1,10 @@
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Mirea.Api.Security.Common.Domain; using Mirea.Api.Security.Common.Domain;
using Mirea.Api.Security.Common.Domain.OAuth2;
using Mirea.Api.Security.Common.Domain.OAuth2.UserInfo;
using Mirea.Api.Security.Common.Interfaces; using Mirea.Api.Security.Common.Interfaces;
using Mirea.Api.Security.Common.OAuth2;
using Mirea.Api.Security.Common.OAuth2.UserInfo;
using Mirea.Api.Security.Common.ViewModel;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -15,6 +16,7 @@ using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using CookieOptions = Mirea.Api.Security.Common.Model.CookieOptions;
namespace Mirea.Api.Security.Services; namespace Mirea.Api.Security.Services;
@ -165,6 +167,7 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
} }
public Uri GetProviderRedirect(HttpContext context, CookieOptionsParameters cookieOptions, string redirectUri, public Uri GetProviderRedirect(HttpContext context, CookieOptionsParameters cookieOptions, string redirectUri,
public Uri GetProviderRedirect(HttpContext context, CookieOptions cookieOptions, string redirectUri,
OAuthProvider provider, Uri callback) OAuthProvider provider, Uri callback)
{ {
var (clientId, _) = providers[provider]; var (clientId, _) = providers[provider];
@ -195,10 +198,10 @@ public class OAuthService(ILogger<OAuthService> logger, Dictionary<OAuthProvider
public (OAuthProvider Provider, Uri Redirect)[] GetAvailableProviders(string redirectUri) => public (OAuthProvider Provider, Uri Redirect)[] GetAvailableProviders(string redirectUri) =>
[.. providers.Select(x => (x.Key, new Uri(redirectUri.TrimEnd('/') + "/?provider=" + (int)x.Key)))]; [.. providers.Select(x => (x.Key, new Uri(redirectUri.TrimEnd('/') + "/?provider=" + (int)x.Key)))];
public async Task<LoginOAuthResult> LoginOAuth(HttpContext context, CookieOptionsParameters cookieOptions, public async Task<LoginOAuth> LoginOAuth(HttpContext context, CookieOptions cookieOptions,
string redirectUrl, string code, string state, CancellationToken cancellation = default) string redirectUrl, string code, string state, CancellationToken cancellation = default)
{ {
var result = new LoginOAuthResult() var result = new LoginOAuth()
{ {
Token = GeneratorKey.GenerateBase64(32) Token = GeneratorKey.GenerateBase64(32)
}; };

View File

@ -1,4 +1,4 @@
using Mirea.Api.Security.Common.Domain; using Mirea.Api.Security.Common.Model;
using System.Linq; using System.Linq;
using System.Security; using System.Security;