Browse Source
Add multi-tenant external login support for IdentityUser
pull/24456/head
maliming
9 months ago
No known key found for this signature in database
GPG Key ID: A646B9CB645ECEA4
6 changed files with
89 additions and
4 deletions
-
modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs
-
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityUserValidator.cs
-
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs
-
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs
-
modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs
-
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs
|
|
|
@ -91,6 +91,22 @@ public class AbpSignInManager : SignInManager<IdentityUser> |
|
|
|
return await PasswordSignInAsync(user, password, isPersistent, lockoutOnFailure); |
|
|
|
} |
|
|
|
|
|
|
|
public override async Task<SignInResult> 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<IdentityUser> FindByEmaiAsync(string email) |
|
|
|
{ |
|
|
|
return await _identityUserManager.FindByEmailInHostAsync(email); |
|
|
|
@ -101,6 +117,11 @@ public class AbpSignInManager : SignInManager<IdentityUser> |
|
|
|
return await _identityUserManager.FindByNameInHostAsync(userName); |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task<IdentityUser> FindByLoginAsync(string loginProvider, string providerKey) |
|
|
|
{ |
|
|
|
return await _identityUserManager.FindByLoginInHostAsync(loginProvider, providerKey); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// This is to call the protection method PreSignInCheck
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
@ -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)); |
|
|
|
} |
|
|
|
|
|
|
|
@ -190,6 +190,13 @@ public interface IIdentityUserRepository : IBasicRepository<IdentityUser, Guid> |
|
|
|
CancellationToken cancellationToken = default |
|
|
|
); |
|
|
|
|
|
|
|
Task<List<IdentityUser>> GetUsersByLoginAsync( |
|
|
|
[NotNull] string loginProvider, |
|
|
|
[NotNull] string providerKey, |
|
|
|
bool includeDetails = false, |
|
|
|
CancellationToken cancellationToken = default |
|
|
|
); |
|
|
|
|
|
|
|
Task<IdentityUser> FindByNormalizedUserNameAsync( |
|
|
|
Guid? tenantId, |
|
|
|
[NotNull] string normalizedUserName, |
|
|
|
|
|
|
|
@ -657,4 +657,34 @@ public class IdentityUserManager : UserManager<IdentityUser>, IDomainService |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task<IdentityUser> FindByLoginInHostAsync(string loginProvider, string providerKey) |
|
|
|
{ |
|
|
|
if (MultiTenancyOptions.Value.UserSharingStrategy == TenantUserSharingStrategy.Isolated) |
|
|
|
{ |
|
|
|
return await base.FindByLoginAsync(loginProvider, providerKey); |
|
|
|
} |
|
|
|
|
|
|
|
using (CurrentTenant.Change(null)) |
|
|
|
{ |
|
|
|
using (DataFilter.Disable<IMultiTenant>()) |
|
|
|
{ |
|
|
|
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<IMultiTenant>()) |
|
|
|
{ |
|
|
|
using (CurrentTenant.Change(hostUser.TenantId)) |
|
|
|
{ |
|
|
|
return await base.FindByLoginAsync(loginProvider, providerKey); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -493,6 +493,15 @@ public class EfCoreIdentityUserRepository : EfCoreRepository<IIdentityDbContext, |
|
|
|
.ToListAsync(GetCancellationToken(cancellationToken)); |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task<List<IdentityUser>> 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<IdentityUser> FindByNormalizedUserNameAsync(Guid? tenantId, string normalizedUserName, bool includeDetails = true, CancellationToken cancellationToken = default) |
|
|
|
{ |
|
|
|
return await (await GetDbSetAsync()) |
|
|
|
|
|
|
|
@ -485,6 +485,14 @@ public class MongoIdentityUserRepository : MongoDbRepository<IAbpIdentityMongoDb |
|
|
|
.ToListAsync(cancellationToken: cancellationToken); |
|
|
|
} |
|
|
|
|
|
|
|
public virtual async Task<List<IdentityUser>> 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<IdentityUser> FindByNormalizedUserNameAsync(Guid? tenantId, string normalizedUserName, bool includeDetails = true, CancellationToken cancellationToken = default) |
|
|
|
{ |
|
|
|
return await (await GetQueryableAsync(cancellationToken)) |
|
|
|
|