using Abp.Configuration; using Abp.Dependency; using Abp.Domain.Uow; using Abp.Extensions; using Abp.Runtime.Security; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; using System.Security.Claims; using VberZero.Authorization.Users; using VberZero.BaseSystem.Users; using VberZero.Settings; namespace VberZero.Authorization; public class VzSignInManager : SignInManager, ITransientDependency { private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly ISettingManager _settingManager; private readonly IConfiguration _configuration; public VzSignInManager( VzUserManager userManager, IHttpContextAccessor contextAccessor, VzUserClaimsPrincipalFactory claimsFactory, IOptions optionsAccessor, ILogger logger, IUnitOfWorkManager unitOfWorkManager, ISettingManager settingManager, IAuthenticationSchemeProvider schemes, IUserConfirmation userConfirmation, IConfiguration configuration) : base( userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, userConfirmation) { _unitOfWorkManager = unitOfWorkManager; _settingManager = settingManager; _configuration = configuration; } public virtual async Task SignInOrTwoFactorAsync(AbpLoginResult loginResult, bool isPersistent, bool? rememberBrowser = null, string loginProvider = null, bool bypassTwoFactor = false) { if (loginResult.Result != VzLoginResultType.Success) { throw new ArgumentException("loginResult.Result should be success in order to sign in!"); } using (_unitOfWorkManager.Current.SetTenantId(loginResult.Tenant.Id)) { await UserManager.As().InitializeOptionsAsync(loginResult.Tenant.Id); if (!bypassTwoFactor && IsTrue(VzSettingNames.UserManagement.TwoFactorLogin.IsEnabled, loginResult.Tenant.Id)) { if (await UserManager.GetTwoFactorEnabledAsync(loginResult.User)) { if ((await UserManager.GetValidTwoFactorProvidersAsync(loginResult.User)).Count > 0) { if (!await IsTwoFactorClientRememberedAsync(loginResult.User) || rememberBrowser == false) { await Context.SignInAsync( IdentityConstants.TwoFactorUserIdScheme, StoreTwoFactorInfo(loginResult.User, loginProvider) ); return SignInResult.TwoFactorRequired; } } } } if (loginProvider != null) { await Context.SignOutAsync(IdentityConstants.ExternalScheme); } await SignInAsync(loginResult.User, isPersistent, loginProvider); return SignInResult.Success; } } public virtual async Task SignOutAndSignInAsync(ClaimsIdentity identity, bool isPersistent) { await SignOutAsync(); await SignInAsync(identity, isPersistent); } /// /// /// /// /// /// public virtual async Task SignInAsync(ClaimsIdentity identity, bool isPersistent) { if (!int.TryParse(_configuration["AuthSession:ExpireTimeInMinutes"], out int expireTime)) { expireTime = VzConsts.SignInExpireMinutes; } await Context.SignInAsync(IdentityConstants.ApplicationScheme, new ClaimsPrincipal(identity), new AuthenticationProperties { IsPersistent = isPersistent, ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(expireTime), AllowRefresh = true }); } public override async Task SignInAsync(User user, bool isPersistent, string authenticationMethod = null) { await _unitOfWorkManager.WithUnitOfWorkAsync(async () => { await base.SignInAsync(user, isPersistent, authenticationMethod); }); } protected virtual ClaimsPrincipal StoreTwoFactorInfo(User user, string loginProvider) { var identity = new ClaimsIdentity(IdentityConstants.TwoFactorUserIdScheme); identity.AddClaim(new Claim(ClaimTypes.Name, user.Id.ToString())); if (user.TenantId.HasValue) { identity.AddClaim(new Claim(AbpClaimTypes.TenantId, user.TenantId.Value.ToString())); } if (loginProvider != null) { identity.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, loginProvider)); } return new ClaimsPrincipal(identity); } public async Task GetVerifiedTenantIdAsync() { var result = await Context.AuthenticateAsync(IdentityConstants.TwoFactorUserIdScheme); if (result.Principal == null) { return null; } return VzClaimsIdentityHelper.GetTenantId(result.Principal); } public override async Task IsTwoFactorClientRememberedAsync(User user) { var result = await Context.AuthenticateAsync(IdentityConstants.TwoFactorRememberMeScheme); return result.Principal != null && result.Principal.FindFirstValue(ClaimTypes.Name) == user.Id.ToString() && VzClaimsIdentityHelper.GetTenantId(result.Principal) == user.TenantId; } public override async Task RememberTwoFactorClientAsync(User user) { //var rememberBrowserIdentity = new ClaimsIdentity(IdentityConstants.TwoFactorRememberMeScheme); //rememberBrowserIdentity.AddClaim(new Claim(ClaimTypes.Name, user.Id.ToString())); //if (user.TenantId.HasValue) //{ // rememberBrowserIdentity.AddClaim(new Claim(AbpClaimTypes.TenantId, user.TenantId.Value.ToString())); //} //if (UserManager.SupportsUserSecurityStamp) //{ // var stamp = await UserManager.GetSecurityStampAsync(user); // rememberBrowserIdentity.AddClaim(new Claim(Options.ClaimsIdentity.SecurityStampClaimType, stamp)); //} //await Context.SignInAsync(IdentityConstants.TwoFactorRememberMeScheme, // new ClaimsPrincipal(rememberBrowserIdentity), // new AuthenticationProperties { IsPersistent = true }); var principal = await StoreRememberClient(user); await Context.SignInAsync(IdentityConstants.TwoFactorRememberMeScheme, principal, new AuthenticationProperties { IsPersistent = true }); } protected virtual async Task StoreRememberClient(User user) { var rememberBrowserIdentity = new ClaimsIdentity(IdentityConstants.TwoFactorRememberMeScheme); rememberBrowserIdentity.AddClaim(new Claim(ClaimTypes.Name, user.Id.ToString())); if (user.TenantId.HasValue) { rememberBrowserIdentity.AddClaim(new Claim(AbpClaimTypes.TenantId, user.TenantId.Value.ToString())); } if (UserManager.SupportsUserSecurityStamp) { var stamp = await UserManager.GetSecurityStampAsync(user); rememberBrowserIdentity.AddClaim(new Claim(Options.ClaimsIdentity.SecurityStampClaimType, stamp)); } return new ClaimsPrincipal(rememberBrowserIdentity); } private bool IsTrue(string settingName, int? tenantId) { return tenantId == null ? _settingManager.GetSettingValueForApplication(settingName) : _settingManager.GetSettingValueForTenant(settingName, tenantId.Value); } }