diff --git a/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs b/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs index 66c57f4c39..dc305c819c 100644 --- a/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs @@ -91,6 +91,22 @@ public class AbpSignInManager : SignInManager return await PasswordSignInAsync(user, password, isPersistent, lockoutOnFailure); } + public override async Task ExternalLoginSignInAsync(string loginProvider, string providerKey, bool isPersistent, bool bypassTwoFactor) + { + var user = await FindByLoginAsync(loginProvider, providerKey); + if (user == null) + { + return SignInResult.Failed; + } + + var error = await PreSignInCheck(user); + if (error != null) + { + return error; + } + return await SignInOrTwoFactorAsync(user, isPersistent, loginProvider, bypassTwoFactor); + } + public virtual async Task FindByEmaiAsync(string email) { return await _identityUserManager.FindByEmailInHostAsync(email); @@ -101,6 +117,11 @@ public class AbpSignInManager : SignInManager return await _identityUserManager.FindByNameInHostAsync(userName); } + public virtual async Task FindByLoginAsync(string loginProvider, string providerKey) + { + return await _identityUserManager.FindByLoginInHostAsync(loginProvider, providerKey); + } + /// /// This is to call the protection method PreSignInCheck /// diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityUserValidator.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityUserValidator.cs index 2cce94a57f..5dc6225761 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityUserValidator.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityUserValidator.cs @@ -170,10 +170,15 @@ namespace Volo.Abp.Identity } else { - var owner = await manager.FindByNameAsync(userName); + IdentityUser owner; + using (CurrentTenant.Change(user.TenantId)) + { + owner = await manager.FindByNameAsync(userName); + } if (owner != null && !string.Equals(await manager.GetUserIdAsync(owner), await manager.GetUserIdAsync(user)) && - owner.TenantId == user.TenantId) + owner.TenantId == user.TenantId && + owner.NormalizedUserName != manager.NormalizeName(userName)) { errors.Add(ErrorDescriber.DuplicateUserName(userName)); } @@ -197,10 +202,15 @@ namespace Volo.Abp.Identity errors.Add(ErrorDescriber.InvalidEmail(email)); return errors; } - var owner = await manager.FindByEmailAsync(email); + IdentityUser owner; + using (CurrentTenant.Change(user.TenantId)) + { + owner = await manager.FindByEmailAsync(email); + } if (owner != null && !string.Equals(await manager.GetUserIdAsync(owner), await manager.GetUserIdAsync(user)) && - owner.TenantId == user.TenantId) + owner.TenantId == user.TenantId && + owner.NormalizedEmail != manager.NormalizeEmail(email)) { errors.Add(ErrorDescriber.DuplicateEmail(email)); } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs index d92717c44c..9b7b86f8d4 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs @@ -190,6 +190,13 @@ public interface IIdentityUserRepository : IBasicRepository CancellationToken cancellationToken = default ); + Task> GetUsersByLoginAsync( + [NotNull] string loginProvider, + [NotNull] string providerKey, + bool includeDetails = false, + CancellationToken cancellationToken = default + ); + Task FindByNormalizedUserNameAsync( Guid? tenantId, [NotNull] string normalizedUserName, diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs index 8cd76acd0e..a893bcf530 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs @@ -657,4 +657,34 @@ public class IdentityUserManager : UserManager, IDomainService } } } + + public virtual async Task FindByLoginInHostAsync(string loginProvider, string providerKey) + { + if (MultiTenancyOptions.Value.UserSharingStrategy == TenantUserSharingStrategy.Isolated) + { + return await base.FindByLoginAsync(loginProvider, providerKey); + } + + using (CurrentTenant.Change(null)) + { + using (DataFilter.Disable()) + { + var hostusers = await UserRepository.GetUsersByLoginAsync(loginProvider, providerKey, cancellationToken: CancellationToken); + //host user first + var hostUser = hostusers.FirstOrDefault(x => x.TenantId == null) ?? hostusers.FirstOrDefault(); + if (hostUser == null) + { + return null; + } + + using (DataFilter.Enable()) + { + using (CurrentTenant.Change(hostUser.TenantId)) + { + return await base.FindByLoginAsync(loginProvider, providerKey); + } + } + } + } + } } diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs index 459a73593c..e472448fc9 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs @@ -493,6 +493,15 @@ public class EfCoreIdentityUserRepository : EfCoreRepository> GetUsersByLoginAsync(string loginProvider, string providerKey, bool includeDetails = false, CancellationToken cancellationToken = default) + { + return await (await GetDbSetAsync()) + .IncludeDetails(includeDetails) + .OrderBy(x => x.Id) + .Where(u => u.Logins.Any(login => login.LoginProvider == loginProvider && login.ProviderKey == providerKey)) + .ToListAsync(GetCancellationToken(cancellationToken)); + } + public virtual async Task FindByNormalizedUserNameAsync(Guid? tenantId, string normalizedUserName, bool includeDetails = true, CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs index 718d461b87..c2c23344eb 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs @@ -485,6 +485,14 @@ public class MongoIdentityUserRepository : MongoDbRepository> GetUsersByLoginAsync(string loginProvider, string providerKey, bool includeDetails = false, CancellationToken cancellationToken = default) + { + return await (await GetQueryableAsync(cancellationToken)) + .OrderBy(x => x.Id) + .Where(u => u.Logins.Any(login => login.LoginProvider == loginProvider && login.ProviderKey == providerKey)) + .ToListAsync(cancellationToken: cancellationToken); + } + public virtual async Task FindByNormalizedUserNameAsync(Guid? tenantId, string normalizedUserName, bool includeDetails = true, CancellationToken cancellationToken = default) { return await (await GetQueryableAsync(cancellationToken))