- ABP Framework version: v9.0.3
- UI Type Blazor Server
- Database System: EF Core (SQL Server)
- Tiered (for MVC) or Auth Server Separated (for Angular): yes
- Steps to reproduce the issue:
Our app is setup to allow logins from an external active directory. For example, we're calling: context.Services.AddAuthentication().AddOpenIdConnect(....details...). This has been working perfectly. On our login screen they can login with either a local user/pass or click a button that takes them to the external IDP and comes back and creates an account.
We're testing upgrading to .net 9 and abp 9. That's gone well, except now when a user logins with the external IDP and comes back they are prompted to create a local password.
Here's the screen they see after authenticating with the external IDP:
I suspect we've missed something when initially configuring this flow. From what I can tell if the PasswordHash is null in the database then they see this prompt. Again prior to abp 9, they never saw this prompt if they logged in with an external user. And after setting the password I noticed we can login with that new password and email AND also login with the external ad still with no further prompts.
Has any behavior changed in how the flow works with checking for passwords? I also noticed there is a 'IsExternal' property on the ABPUsers table. Is this related or need to be set?
9 Answer(s)
-
0
Not sure if this is helpful or related, but we are extending the IdentityUserManager to mark external users as email confirmed on creation so they don't have to validate their email since they used an External IDP.
I suspect this is a weird way to solve this scenario. Is there a better approach to identify external users and make sure they are logged in without having to set passwords or confirm emails?
[Dependency(ReplaceServices = true)] [ExposeServices(typeof(IdentityUserManager))] public class XXXXIdentityUserManager( IdentityUserStore store, IIdentityRoleRepository roleRepository, IIdentityUserRepository userRepository, IOptions<IdentityOptions> optionsAccessor, IPasswordHasher<IdentityUser> passwordHasher, IEnumerable<IUserValidator<IdentityUser>> userValidators, IEnumerable<IPasswordValidator<IdentityUser>> passwordValidators, ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, IServiceProvider services, ILogger<IdentityUserManager> logger, ICancellationTokenProvider cancellationTokenProvider, IOrganizationUnitRepository organizationUnitRepository, ISettingProvider settingProvider, IDistributedEventBus distributedEventBus, IIdentityLinkUserRepository identityLinkUserRepository, IDistributedCache<AbpDynamicClaimCacheItem> dynamicClaimCache) : IdentityUserManager(store, roleRepository, userRepository, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger, cancellationTokenProvider, organizationUnitRepository, settingProvider, distributedEventBus, identityLinkUserRepository, dynamicClaimCache) { public override async Task<IdentityResult> CreateAsync(IdentityUser user) { if (user.PasswordHash == null && ( user.Email.EndsWith("@XXXXX.com", StringComparison.InvariantCultureIgnoreCase) || user.Email.EndsWith("@XXXXX.com", StringComparison.InvariantCultureIgnoreCase))) { user.SetEmailConfirmed(true); } return await base.CreateAsync(user); } }
-
0
Hi, this is the expected behavior (https://abp.io/docs/latest/modules/account-pro#social-account-security-setting):
Users who register via both local registration and external/social login using the same email address will be required to enter their local password on the first external/social login.
You can disable this option if you want.
-
0
I have toggled that option on/off and confirmed it so in the abpsettings table. It's always asking for the password. I've even created a brand new single layer blazor server app with abp 9.0.3. And the only code change I make is to wire up the auth with these settings
On the login screen I click the new AD button:
I successfully go over to microsoft, I login, come back and I see this:
At this point I check the abpuser table in the database. I see the user created and the password is null and isexternal = 0 (not sure if this field matters or not).
Here's what I see in the database tables:
I'm not sure at this point what else i'm missing to make it stop asking for the password on external logins
-
1
-
0
Ah! That addresses the issue. I assumed since the provider key was null, it would apply for the null/host tenant.
Just for clarity - since the providerkey on the setting points to the entity id that it's referring too and in this case it was for a setting for the null/host tenant the provider name needs to be a 'G' instead of 'T'? Outside of changing it in the database (which I'm ok with), is there anything else that would handle this scenerio automatically. I assume if I didn't have multi-tenancy set to true, this would have worked if it was G or T?
-
0
Correction, this is still an issue for me. I think I tested this against account where I had set the password and thought it was fixed.
This is getting frustrating because I'm spending more time that I should be on resolving this and feel like I'm missing something simple. I need specific guidance to get past this issue. I'll restate what behavior I'm looking for:
1 - Users can create either a local account or use an external login. 2 - If a user registers a new account with an external login they are never prompted to create a password.
In my use-case most of the time people are just going to login with their external account and never bother or think about a local account. In version 8, my users were never asked to create the password when using an external login. But upgrading to 9 they are.
The only way I've gotten it to not ask for the creation of a password is by making "Allow to register and log in with local username and password" be set to false. But of course that's not ideal, because I also need to allow local accounts in some cases.
The "Require Local Password on Social Account Linking" setting seems to not actually not be related to my scenario. Based on the wording, it seems to be related to where they have a local account AND are wanting to also link an external account.
Is what I'm asking possible? Can I have external login accounts without password and also have local accounts with passwords? Is there a way to trick the code to not prompt the creation of a new password?
-
0
hi
Sorry about that. We will reconsider the changes. You can use this file to override the 9.0 behavior.
https://we.tl/t-wKuvMQw8q0
-
0
No worries! I've tested the custom LoginModel and the 2 checks that you commented out work great. That puts the behavior back to how I was intending to use it. Thank you!
I do understand the intention with what ya'll were going for, e.g. ensuring that external logins have a local user/pass so that they don't lose access to an account if the external login stops working. Maybe there's a tenant setting (or maybe even a per-external provider configuration) that says "if externallogin and (thisSpecificExternalLoginProvider.RequiresLocalPassword && user.PasswordHash is null) then redirect to change password"
Just my 2 cents, I know you guys have thought through this a lot.
Again, Thank you!
-
0
Thanks. I have created an internal issue to tracking this case.