From 0ae62dcfe98dd73dcc476d18b30bdf2b19579853 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 23 May 2022 14:55:58 +0800 Subject: [PATCH 1/5] Add CanObtainUserInfoWithoutPassword to IExternalLoginProvider --- .../Identity/AspNetCore/AbpSignInManager.cs | 14 +++++++-- .../Abp/Identity/ExternalLoginProviderBase.cs | 29 +++++++++++++++---- .../Abp/Identity/IExternalLoginProvider.cs | 8 +++-- .../AspNetCore/FakeExternalLoginProvider.cs | 5 ++++ 4 files changed, 46 insertions(+), 10 deletions(-) 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 313be4ae3f..946435e87c 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 @@ -49,11 +49,21 @@ public class AbpSignInManager : SignInManager var user = await UserManager.FindByNameAsync(userName); if (user == null) { - user = await externalLoginProvider.CreateUserAsync(userName, externalLoginProviderInfo.Name); + user = externalLoginProvider.CanObtainUserInfoWithoutPassword + ? await externalLoginProvider.CreateUserAsync(userName, externalLoginProviderInfo.Name) + : await externalLoginProvider.CreateUserAsync(userName, externalLoginProviderInfo.Name, password); } else { - await externalLoginProvider.UpdateUserAsync(user, externalLoginProviderInfo.Name); + if (externalLoginProvider.CanObtainUserInfoWithoutPassword) + { + await externalLoginProvider.UpdateUserAsync(user, externalLoginProviderInfo.Name); + } + else + { + await externalLoginProvider.UpdateUserAsync(user, externalLoginProviderInfo.Name, password); + } + } return await SignInOrTwoFactorAsync(user, isPersistent); diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs index cfefad2a95..ba85576ace 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs @@ -16,6 +16,8 @@ public abstract class ExternalLoginProviderBase : IExternalLoginProvider protected IdentityUserManager UserManager { get; } protected IIdentityUserRepository IdentityUserRepository { get; } protected IOptions IdentityOptions { get; } + + public bool CanObtainUserInfoWithoutPassword { get; set; } protected ExternalLoginProviderBase( IGuidGenerator guidGenerator, @@ -29,19 +31,21 @@ public abstract class ExternalLoginProviderBase : IExternalLoginProvider UserManager = userManager; IdentityUserRepository = identityUserRepository; IdentityOptions = identityOptions; + CanObtainUserInfoWithoutPassword = true; } public abstract Task TryAuthenticateAsync(string userName, string plainPassword); - + public abstract Task IsEnabledAsync(); - public virtual async Task CreateUserAsync(string userName, string providerName) + public virtual async Task CreateUserAsync(string userName, string providerName, string plainPassword = null) { await IdentityOptions.SetAsync(); - var externalUser = await GetUserInfoAsync(userName); - NormalizeExternalLoginUserInfo(externalUser, userName); + var externalUser = CanObtainUserInfoWithoutPassword ? await GetUserInfoAsync(userName) : await GetUserInfoAsync(userName, plainPassword); + NormalizeExternalLoginUserInfo(externalUser, userName); + var user = new IdentityUser( GuidGenerator.Create(), userName, @@ -78,11 +82,17 @@ public abstract class ExternalLoginProviderBase : IExternalLoginProvider return user; } - public virtual async Task UpdateUserAsync(IdentityUser user, string providerName) + public virtual async Task UpdateUserAsync(IdentityUser user, string providerName, string plainPassword = null) { await IdentityOptions.SetAsync(); - var externalUser = await GetUserInfoAsync(user); + if (!CanObtainUserInfoWithoutPassword) + { + Check.NotNullOrWhiteSpace(plainPassword, nameof(plainPassword)); + } + + var externalUser = CanObtainUserInfoWithoutPassword ? await GetUserInfoAsync(user) : await GetUserInfoAsync(user, plainPassword); + NormalizeExternalLoginUserInfo(externalUser, user.UserName); if (!externalUser.Name.IsNullOrWhiteSpace()) @@ -147,10 +157,17 @@ public abstract class ExternalLoginProviderBase : IExternalLoginProvider protected abstract Task GetUserInfoAsync(string userName); + protected abstract Task GetUserInfoAsync(string userName, string plainPassword); + protected virtual Task GetUserInfoAsync(IdentityUser user) { return GetUserInfoAsync(user.UserName); } + + protected virtual Task GetUserInfoAsync(IdentityUser user, string plainPassword) + { + return GetUserInfoAsync(user.UserName, plainPassword); + } private static void NormalizeExternalLoginUserInfo( ExternalLoginUserInfo externalUser, diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProvider.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProvider.cs index 52d3895d13..7621c54de6 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProvider.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProvider.cs @@ -4,6 +4,8 @@ namespace Volo.Abp.Identity; public interface IExternalLoginProvider { + bool CanObtainUserInfoWithoutPassword { get; set; } + /// /// Used to try authenticate a user by this source. /// @@ -18,8 +20,9 @@ public interface IExternalLoginProvider /// /// User name /// The name of this provider + /// Optional, plain password of the user /// Newly created user - Task CreateUserAsync(string userName, string providerName); + Task CreateUserAsync(string userName, string providerName, string plainPassword = null); /// /// This method is called after an existing user is authenticated by this source. @@ -27,7 +30,8 @@ public interface IExternalLoginProvider /// /// The name of this provider /// The user that can be updated - Task UpdateUserAsync(IdentityUser user, string providerName); + /// Optional, plain password of the user + Task UpdateUserAsync(IdentityUser user, string providerName, string plainPassword = null); /// /// Return a value indicating whether this source is enabled. diff --git a/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs b/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs index fbfc0e2ef6..038e8cde0c 100644 --- a/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs +++ b/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs @@ -60,4 +60,9 @@ public class FakeExternalLoginProvider : ExternalLoginProviderBase, ITransientDe } ); } + + protected override Task GetUserInfoAsync(string userName, string plainPassword) + { + return GetUserInfoAsync(userName); + } } From 7486582023e7835313135e81e65ad62730b7ee2a Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 23 May 2022 15:39:01 +0800 Subject: [PATCH 2/5] Add IExternalLoginProviderWithPassword --- .../Identity/AspNetCore/AbpSignInManager.cs | 20 ++++++--- .../Abp/Identity/ExternalLoginProviderBase.cs | 45 +++++++++++++------ .../Abp/Identity/IExternalLoginProvider.cs | 8 ++-- .../IExternalLoginProviderWithPassword.cs | 26 +++++++++++ .../AspNetCore/FakeExternalLoginProvider.cs | 5 +++ 5 files changed, 79 insertions(+), 25 deletions(-) create mode 100644 modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProviderWithPassword.cs 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 946435e87c..49959d930d 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 @@ -49,21 +49,27 @@ public class AbpSignInManager : SignInManager var user = await UserManager.FindByNameAsync(userName); if (user == null) { - user = externalLoginProvider.CanObtainUserInfoWithoutPassword - ? await externalLoginProvider.CreateUserAsync(userName, externalLoginProviderInfo.Name) - : await externalLoginProvider.CreateUserAsync(userName, externalLoginProviderInfo.Name, password); + if (!externalLoginProvider.CanObtainUserInfoWithoutPassword() && + externalLoginProvider is IExternalLoginProviderWithPassword externalLoginProviderWithPassword) + { + user = await externalLoginProviderWithPassword.CreateUserAsync(userName, externalLoginProviderInfo.Name, password); + } + else + { + user = await externalLoginProvider.CreateUserAsync(userName, externalLoginProviderInfo.Name); + } } else { - if (externalLoginProvider.CanObtainUserInfoWithoutPassword) + if (!externalLoginProvider.CanObtainUserInfoWithoutPassword() && + externalLoginProvider is IExternalLoginProviderWithPassword externalLoginProviderWithPassword) { - await externalLoginProvider.UpdateUserAsync(user, externalLoginProviderInfo.Name); + await externalLoginProviderWithPassword.UpdateUserAsync(user, externalLoginProviderInfo.Name, password); } else { - await externalLoginProvider.UpdateUserAsync(user, externalLoginProviderInfo.Name, password); + await externalLoginProvider.UpdateUserAsync(user, externalLoginProviderInfo.Name); } - } return await SignInOrTwoFactorAsync(user, isPersistent); diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs index ba85576ace..a19b0fb7c8 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs @@ -9,16 +9,13 @@ using Volo.Abp.MultiTenancy; namespace Volo.Abp.Identity; -public abstract class ExternalLoginProviderBase : IExternalLoginProvider +public abstract class ExternalLoginProviderBase : IExternalLoginProvider, IExternalLoginProviderWithPassword { protected IGuidGenerator GuidGenerator { get; } protected ICurrentTenant CurrentTenant { get; } protected IdentityUserManager UserManager { get; } protected IIdentityUserRepository IdentityUserRepository { get; } protected IOptions IdentityOptions { get; } - - public bool CanObtainUserInfoWithoutPassword { get; set; } - protected ExternalLoginProviderBase( IGuidGenerator guidGenerator, ICurrentTenant currentTenant, @@ -31,19 +28,32 @@ public abstract class ExternalLoginProviderBase : IExternalLoginProvider UserManager = userManager; IdentityUserRepository = identityUserRepository; IdentityOptions = identityOptions; - CanObtainUserInfoWithoutPassword = true; } public abstract Task TryAuthenticateAsync(string userName, string plainPassword); public abstract Task IsEnabledAsync(); - public virtual async Task CreateUserAsync(string userName, string providerName, string plainPassword = null) + public virtual async Task CreateUserAsync(string userName, string providerName) { await IdentityOptions.SetAsync(); - var externalUser = CanObtainUserInfoWithoutPassword ? await GetUserInfoAsync(userName) : await GetUserInfoAsync(userName, plainPassword); + var externalUser = await GetUserInfoAsync(userName); + + return await CreateUserAsync(externalUser, userName, providerName); + } + public virtual async Task CreateUserAsync(string userName, string providerName, string plainPassword) + { + await IdentityOptions.SetAsync(); + + var externalUser = await GetUserInfoAsync(userName, plainPassword); + + return await CreateUserAsync(externalUser, userName, providerName); + } + + protected virtual async Task CreateUserAsync(ExternalLoginUserInfo externalUser, string userName, string providerName) + { NormalizeExternalLoginUserInfo(externalUser, userName); var user = new IdentityUser( @@ -82,17 +92,26 @@ public abstract class ExternalLoginProviderBase : IExternalLoginProvider return user; } - public virtual async Task UpdateUserAsync(IdentityUser user, string providerName, string plainPassword = null) + public virtual async Task UpdateUserAsync(IdentityUser user, string providerName) { await IdentityOptions.SetAsync(); + + var externalUser = await GetUserInfoAsync(user); - if (!CanObtainUserInfoWithoutPassword) - { - Check.NotNullOrWhiteSpace(plainPassword, nameof(plainPassword)); - } + await UpdateUserAsync(user, externalUser, providerName); + } + + public virtual async Task UpdateUserAsync(IdentityUser user, string providerName, string plainPassword) + { + await IdentityOptions.SetAsync(); - var externalUser = CanObtainUserInfoWithoutPassword ? await GetUserInfoAsync(user) : await GetUserInfoAsync(user, plainPassword); + var externalUser = await GetUserInfoAsync(user, plainPassword); + await UpdateUserAsync(user, externalUser, providerName); + } + + protected virtual async Task UpdateUserAsync(IdentityUser user, ExternalLoginUserInfo externalUser ,string providerName) + { NormalizeExternalLoginUserInfo(externalUser, user.UserName); if (!externalUser.Name.IsNullOrWhiteSpace()) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProvider.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProvider.cs index 7621c54de6..2b9a267369 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProvider.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProvider.cs @@ -4,7 +4,7 @@ namespace Volo.Abp.Identity; public interface IExternalLoginProvider { - bool CanObtainUserInfoWithoutPassword { get; set; } + bool CanObtainUserInfoWithoutPassword(); /// /// Used to try authenticate a user by this source. @@ -20,9 +20,8 @@ public interface IExternalLoginProvider /// /// User name /// The name of this provider - /// Optional, plain password of the user /// Newly created user - Task CreateUserAsync(string userName, string providerName, string plainPassword = null); + Task CreateUserAsync(string userName, string providerName); /// /// This method is called after an existing user is authenticated by this source. @@ -30,8 +29,7 @@ public interface IExternalLoginProvider /// /// The name of this provider /// The user that can be updated - /// Optional, plain password of the user - Task UpdateUserAsync(IdentityUser user, string providerName, string plainPassword = null); + Task UpdateUserAsync(IdentityUser user, string providerName); /// /// Return a value indicating whether this source is enabled. diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProviderWithPassword.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProviderWithPassword.cs new file mode 100644 index 0000000000..ae91079a76 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProviderWithPassword.cs @@ -0,0 +1,26 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.Identity +{ + public interface IExternalLoginProviderWithPassword + { + /// + /// This method is called when a user is authenticated by this source but the user does not exists yet. + /// So, the source should create the user and fill the properties. + /// + /// User name + /// The name of this provider + /// The plain password of the user + /// Newly created user + Task CreateUserAsync(string userName, string providerName, string plainPassword); + + /// + /// This method is called after an existing user is authenticated by this source. + /// It can be used to update some properties of the user by the source. + /// + /// The name of this provider + /// The user that can be updated + /// The plain password of the user + Task UpdateUserAsync(IdentityUser user, string providerName, string plainPassword); + } +} \ No newline at end of file diff --git a/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs b/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs index 038e8cde0c..8cfb3df04d 100644 --- a/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs +++ b/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs @@ -28,6 +28,11 @@ public class FakeExternalLoginProvider : ExternalLoginProviderBase, ITransientDe } + public override bool CanObtainUserInfoWithoutPassword() + { + return true; + } + public override Task TryAuthenticateAsync(string userName, string plainPassword) { return Task.FromResult( From cf0bc4bab702a55b7e706778f9821749bfd6c0a5 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 23 May 2022 15:41:07 +0800 Subject: [PATCH 3/5] Update ExternalLoginProviderBase --- .../Volo/Abp/Identity/ExternalLoginProviderBase.cs | 5 +++++ .../Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs index a19b0fb7c8..ce1680f5ea 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs @@ -30,6 +30,11 @@ public abstract class ExternalLoginProviderBase : IExternalLoginProvider, IExter IdentityOptions = identityOptions; } + public virtual bool CanObtainUserInfoWithoutPassword() + { + return true; + } + public abstract Task TryAuthenticateAsync(string userName, string plainPassword); public abstract Task IsEnabledAsync(); diff --git a/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs b/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs index 8cfb3df04d..038e8cde0c 100644 --- a/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs +++ b/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs @@ -28,11 +28,6 @@ public class FakeExternalLoginProvider : ExternalLoginProviderBase, ITransientDe } - public override bool CanObtainUserInfoWithoutPassword() - { - return true; - } - public override Task TryAuthenticateAsync(string userName, string plainPassword) { return Task.FromResult( From 4fbac360755b9ab68c3f1207316c4873255a72f1 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 23 May 2022 16:18:11 +0800 Subject: [PATCH 4/5] Refactor --- .../Identity/AspNetCore/AbpSignInManager.cs | 6 +-- .../Abp/Identity/ExternalLoginProviderBase.cs | 34 +------------ .../ExternalLoginProviderWithPasswordBase.cs | 49 +++++++++++++++++++ .../Abp/Identity/IExternalLoginProvider.cs | 6 +-- .../AspNetCore/FakeExternalLoginProvider.cs | 5 -- 5 files changed, 55 insertions(+), 45 deletions(-) create mode 100644 modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderWithPasswordBase.cs 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 49959d930d..bbba6e63ec 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 @@ -49,8 +49,7 @@ public class AbpSignInManager : SignInManager var user = await UserManager.FindByNameAsync(userName); if (user == null) { - if (!externalLoginProvider.CanObtainUserInfoWithoutPassword() && - externalLoginProvider is IExternalLoginProviderWithPassword externalLoginProviderWithPassword) + if (externalLoginProvider is IExternalLoginProviderWithPassword externalLoginProviderWithPassword) { user = await externalLoginProviderWithPassword.CreateUserAsync(userName, externalLoginProviderInfo.Name, password); } @@ -61,8 +60,7 @@ public class AbpSignInManager : SignInManager } else { - if (!externalLoginProvider.CanObtainUserInfoWithoutPassword() && - externalLoginProvider is IExternalLoginProviderWithPassword externalLoginProviderWithPassword) + if (externalLoginProvider is IExternalLoginProviderWithPassword externalLoginProviderWithPassword) { await externalLoginProviderWithPassword.UpdateUserAsync(user, externalLoginProviderInfo.Name, password); } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs index ce1680f5ea..240bf208d8 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderBase.cs @@ -9,7 +9,7 @@ using Volo.Abp.MultiTenancy; namespace Volo.Abp.Identity; -public abstract class ExternalLoginProviderBase : IExternalLoginProvider, IExternalLoginProviderWithPassword +public abstract class ExternalLoginProviderBase : IExternalLoginProvider { protected IGuidGenerator GuidGenerator { get; } protected ICurrentTenant CurrentTenant { get; } @@ -30,11 +30,6 @@ public abstract class ExternalLoginProviderBase : IExternalLoginProvider, IExter IdentityOptions = identityOptions; } - public virtual bool CanObtainUserInfoWithoutPassword() - { - return true; - } - public abstract Task TryAuthenticateAsync(string userName, string plainPassword); public abstract Task IsEnabledAsync(); @@ -47,15 +42,6 @@ public abstract class ExternalLoginProviderBase : IExternalLoginProvider, IExter return await CreateUserAsync(externalUser, userName, providerName); } - - public virtual async Task CreateUserAsync(string userName, string providerName, string plainPassword) - { - await IdentityOptions.SetAsync(); - - var externalUser = await GetUserInfoAsync(userName, plainPassword); - - return await CreateUserAsync(externalUser, userName, providerName); - } protected virtual async Task CreateUserAsync(ExternalLoginUserInfo externalUser, string userName, string providerName) { @@ -105,16 +91,7 @@ public abstract class ExternalLoginProviderBase : IExternalLoginProvider, IExter await UpdateUserAsync(user, externalUser, providerName); } - - public virtual async Task UpdateUserAsync(IdentityUser user, string providerName, string plainPassword) - { - await IdentityOptions.SetAsync(); - - var externalUser = await GetUserInfoAsync(user, plainPassword); - - await UpdateUserAsync(user, externalUser, providerName); - } - + protected virtual async Task UpdateUserAsync(IdentityUser user, ExternalLoginUserInfo externalUser ,string providerName) { NormalizeExternalLoginUserInfo(externalUser, user.UserName); @@ -181,17 +158,10 @@ public abstract class ExternalLoginProviderBase : IExternalLoginProvider, IExter protected abstract Task GetUserInfoAsync(string userName); - protected abstract Task GetUserInfoAsync(string userName, string plainPassword); - protected virtual Task GetUserInfoAsync(IdentityUser user) { return GetUserInfoAsync(user.UserName); } - - protected virtual Task GetUserInfoAsync(IdentityUser user, string plainPassword) - { - return GetUserInfoAsync(user.UserName, plainPassword); - } private static void NormalizeExternalLoginUserInfo( ExternalLoginUserInfo externalUser, diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderWithPasswordBase.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderWithPasswordBase.cs new file mode 100644 index 0000000000..612091f8ea --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderWithPasswordBase.cs @@ -0,0 +1,49 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; +using Volo.Abp.Guids; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.Identity; + +public abstract class ExternalLoginProviderWithPasswordBase : ExternalLoginProviderBase, IExternalLoginProviderWithPassword +{ + public ExternalLoginProviderWithPasswordBase( + IGuidGenerator guidGenerator, + ICurrentTenant currentTenant, + IdentityUserManager userManager, + IIdentityUserRepository identityUserRepository, + IOptions identityOptions) : + base(guidGenerator, + currentTenant, + userManager, + identityUserRepository, + identityOptions) + { + } + + public async Task CreateUserAsync(string userName, string providerName, string plainPassword) + { + await IdentityOptions.SetAsync(); + + var externalUser = await GetUserInfoAsync(userName, plainPassword); + + return await CreateUserAsync(externalUser, userName, providerName); + } + + public async Task UpdateUserAsync(IdentityUser user, string providerName, string plainPassword) + { + await IdentityOptions.SetAsync(); + + var externalUser = await GetUserInfoAsync(user, plainPassword); + + await UpdateUserAsync(user, externalUser, providerName); + } + + protected abstract Task GetUserInfoAsync(string userName, string plainPassword); + + protected virtual Task GetUserInfoAsync(IdentityUser user, string plainPassword) + { + return GetUserInfoAsync(user.UserName, plainPassword); + } +} \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProvider.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProvider.cs index 2b9a267369..774c5a41db 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProvider.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProvider.cs @@ -4,8 +4,6 @@ namespace Volo.Abp.Identity; public interface IExternalLoginProvider { - bool CanObtainUserInfoWithoutPassword(); - /// /// Used to try authenticate a user by this source. /// @@ -30,10 +28,10 @@ public interface IExternalLoginProvider /// The name of this provider /// The user that can be updated Task UpdateUserAsync(IdentityUser user, string providerName); - + /// /// Return a value indicating whether this source is enabled. /// /// Task IsEnabledAsync(); -} +} \ No newline at end of file diff --git a/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs b/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs index 038e8cde0c..fbfc0e2ef6 100644 --- a/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs +++ b/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/FakeExternalLoginProvider.cs @@ -60,9 +60,4 @@ public class FakeExternalLoginProvider : ExternalLoginProviderBase, ITransientDe } ); } - - protected override Task GetUserInfoAsync(string userName, string plainPassword) - { - return GetUserInfoAsync(userName); - } } From 80ea30be0a63e634495314b12433a72201cf2d9b Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 23 May 2022 18:30:14 +0800 Subject: [PATCH 5/5] Improved --- .../ExternalLoginProviderWithPasswordBase.cs | 27 ++++++++++++++++--- .../IExternalLoginProviderWithPassword.cs | 2 ++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderWithPasswordBase.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderWithPasswordBase.cs index 612091f8ea..e791004fd0 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderWithPasswordBase.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/ExternalLoginProviderWithPasswordBase.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; using Volo.Abp.Guids; @@ -8,22 +9,31 @@ namespace Volo.Abp.Identity; public abstract class ExternalLoginProviderWithPasswordBase : ExternalLoginProviderBase, IExternalLoginProviderWithPassword { + public bool CanObtainUserInfoWithoutPassword { get; } + public ExternalLoginProviderWithPasswordBase( IGuidGenerator guidGenerator, ICurrentTenant currentTenant, IdentityUserManager userManager, IIdentityUserRepository identityUserRepository, - IOptions identityOptions) : + IOptions identityOptions, + bool canObtainUserInfoWithoutPassword = false) : base(guidGenerator, currentTenant, userManager, identityUserRepository, identityOptions) { + CanObtainUserInfoWithoutPassword = canObtainUserInfoWithoutPassword; } public async Task CreateUserAsync(string userName, string providerName, string plainPassword) { + if (CanObtainUserInfoWithoutPassword) + { + return await CreateUserAsync(userName, providerName); + } + await IdentityOptions.SetAsync(); var externalUser = await GetUserInfoAsync(userName, plainPassword); @@ -33,13 +43,24 @@ public abstract class ExternalLoginProviderWithPasswordBase : ExternalLoginProvi public async Task UpdateUserAsync(IdentityUser user, string providerName, string plainPassword) { + if (CanObtainUserInfoWithoutPassword) + { + await UpdateUserAsync(user, providerName); + return; + } + await IdentityOptions.SetAsync(); var externalUser = await GetUserInfoAsync(user, plainPassword); await UpdateUserAsync(user, externalUser, providerName); } - + + protected override Task GetUserInfoAsync(string userName) + { + throw new NotImplementedException($"{nameof(GetUserInfoAsync)} is not implemented default. It should be overriden and implemented by the deriving class!"); + } + protected abstract Task GetUserInfoAsync(string userName, string plainPassword); protected virtual Task GetUserInfoAsync(IdentityUser user, string plainPassword) diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProviderWithPassword.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProviderWithPassword.cs index ae91079a76..fa811c852e 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProviderWithPassword.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IExternalLoginProviderWithPassword.cs @@ -4,6 +4,8 @@ namespace Volo.Abp.Identity { public interface IExternalLoginProviderWithPassword { + bool CanObtainUserInfoWithoutPassword { get; } + /// /// This method is called when a user is authenticated by this source but the user does not exists yet. /// So, the source should create the user and fill the properties.