abpframework / abp

Open-source web application framework for ASP.NET Core! Offers an opinionated architecture to build enterprise software solutions with best practices on top of the .NET. Provides the fundamental infrastructure, cross-cutting-concern implementations, startup templates, application modules, UI themes, tooling and documentation.
https://abp.io
GNU Lesser General Public License v3.0
12.81k stars 3.41k forks source link

isLockedOut for user is different between API and GUI #20139

Closed improwise closed 2 months ago

improwise commented 3 months ago

Is there an existing issue for this?

Description

It seems like there is a difference regarding isLockedOut between querying /users via the API and what is displayed in the GUI. This is using a MAUI Blazor project but probably not related to that.

image

It also seems like Account lockout is true by default for every new user, not sure if this is intended?

Reproduction Steps

No response

Expected behavior

No response

Actual behavior

No response

Regression?

No response

Known Workarounds

No response

Version

8.2

User Interface

MAUI

Database Provider

EF Core (Default)

Tiered or separate authentication server

None (Default)

Operation System

Windows (Default)

Other information

No response

improwise commented 3 months ago

Some context, we are trying to seed users by using IdentityUser identityUserCustomer = new IdentityUser() which worked find in older versions of ABP, but not any more. User is created but can't login due to being locked out by default.

How can we unlock a user from code? We tried something like this when we realized we had to

result = await _identityUserManager.SetLockoutEndDateAsync(identityUser, DateTime.Now.AddDays(-1));

but does not seem to work even though result is successful. But maybe there is something in general that prevents this in a seeder as things like

var result = await _identityUserManager.ChangePasswordAsync(identityUserAdmin, "1q2w3E*", "!" + "Admin" + "1");

does not seem to work either even though it also returns successful.

(All this worked in ABP 5 so there must have been some changes since then)

maliming commented 3 months ago

hi

we are trying to seed users by using IdentityUser identityUserCustomer = new IdentityUser() which worked find in older versions of ABP, but not any more. User is created but can't login due to being locked out by default.

Can you share some code or a project to reproduce this case?

improwise commented 3 months ago

hi

we are trying to seed users by using IdentityUser identityUserCustomer = new IdentityUser() which worked find in older versions of ABP, but not any more. User is created but can't login due to being locked out by default.

Can you share some code or a project to reproduce this case?

We were not able to find any code on how to do it so we did our own implementation, could probably be improved, now we just looked at the result in debugger.

Code extract below. Please note that it seems like at least in the UI, the "Account lockout" is true by default even when you create a new user in the UI, so it seems to be a default setting (or maybe something that happens if you don't confirm email and phone?). The SetLockoutEndDateAsync() we added now to try but does not seem to have any effect even though returning successful.

 public async Task SeedAsync(DataSeedContext context)
 {
     // Add roles
     if (await _identityRoleManager.FindByNameAsync(Roles.Customer) == null)
     {
         IdentityRole identityRoleCustomer = new IdentityRole(Guid.NewGuid(), Roles.Customer);
         await _identityRoleManager.CreateAsync(identityRoleCustomer);

     }

     // Add users
     if (await _identityUserManager.FindByNameAsync(Roles.Customer.ToLower()) == null)
     {
         IdentityUser identityUser = new IdentityUser(Guid.NewGuid(), Roles.Customer.ToLower(), Roles.Customer.ToLower() + "@company.com");
         identityUser.Name = identityUser.Surname = Roles.Customer.ToLower();

         var result = await _identityUserManager.CreateAsync(identityUser, "!" + Roles.Customer + "1");
         result = await _identityUserManager.AddToRoleAsync(identityUser, Roles.Customer);
         result = await _identityUserManager.SetLockoutEndDateAsync(identityUser, DateTime.Now.AddDays(-1));

     }

    public static class Roles
    {
        public const string Customer = "Customer";

    }

Please note that we are using ABP Commercial and the solution was created by ABP Suite, but I don't think that would make difference here.

maliming commented 3 months ago
dentityUser identityUser = new IdentityUser(Guid.NewGuid(), Roles.Customer.ToLower(), Roles.Customer.ToLower() + "@company.com");
identityUser.Name = identityUser.Surname = Roles.Customer.ToLower();

var result = await _identityUserManager.CreateAsync(identityUser, "!" + Roles.Customer + "1");

// Set a breakpoint here to see the `identityUser's` `LockoutEnabled` and `LockoutEnd` properties.

result = await _identityUserManager.AddToRoleAsync(identityUser, Roles.Customer);

result = await _identityUserManager.SetLockoutEnabledAsync(identityUser, false)
result = await _identityUserManager.SetLockoutEndDateAsync(identityUser, null)
maliming commented 3 months ago

If it still does not working, Please share a simple project.

https://wetransfer.com/

improwise commented 3 months ago
dentityUser identityUser = new IdentityUser(Guid.NewGuid(), Roles.Customer.ToLower(), Roles.Customer.ToLower() + "@company.com");
identityUser.Name = identityUser.Surname = Roles.Customer.ToLower();

var result = await _identityUserManager.CreateAsync(identityUser, "!" + Roles.Customer + "1");

// Set a breakpoint here to see the `identityUser's` `LockoutEnabled` and `LockoutEnd` properties.

result = await _identityUserManager.AddToRoleAsync(identityUser, Roles.Customer);

result = await _identityUserManager.SetLockoutEnabledAsync(identityUser, false)
result = await _identityUserManager.SetLockoutEndDateAsync(identityUser, null)

Thanks, will give it a try as soon as I get an opportunity and report back. This probably won't change the underlying problem though I guess with the API and UI saying different things and also that new accounts being lockedout by default even when created via the UI (unless that is by design?).

improwise commented 3 months ago

Something is definitely wrong here as even the admin account is listed as being locked out in the UI on a newly created DB. It works for login though.

image

maliming commented 3 months ago

hi

Please share a project and steps, Thanks

https://wetransfer.com/ liming.ma@volosoft.com

improwise commented 2 months ago

hi

Please share a project and steps, Thanks

https://wetransfer.com/ liming.ma@volosoft.com

HI,

To reproduce, just create a new project with CLI and run it, this time we used "abp new Acme.BookStore -t app -u blazor-server --mobile none" but previously it was MAUI Blazor with ABP Suite so probably the same for all. Login and select Edit user "admin" and you will see that the Admin user has "Account lockout" enabled.

API will also say the same thing

/api/identity/users

{
  "totalCount": 1,
  "items": [
    {
      "tenantId": null,
      "userName": "admin",
      "name": "admin",
      "surname": null,
      "email": "admin@abp.io",
      "emailConfirmed": false,
      "phoneNumber": null,
      "phoneNumberConfirmed": false,
      "isActive": true,
      "lockoutEnabled": true,
      "accessFailedCount": 0,
      "lockoutEnd": null,
      "concurrencyStamp": "95419f3a90a94e8eab210375c606240d",
      "entityVersion": 0,
      "lastPasswordChangeTime": "2024-07-05T09:53:28.3711649+00:00",
      "isDeleted": false,
      "deleterId": null,
      "deletionTime": null,
      "lastModificationTime": null,
      "lastModifierId": null,
      "creationTime": "2024-07-05T11:53:28.489551",
      "creatorId": null,
      "id": "c8af3e1c-19d8-58c0-b0ea-3a13947cfaf5",
      "extraProperties": {}
    }
  ]
}

Creating a new user, it will also default to being locked out.

Please note that I have not yet had a chance to use that code snippet for creating users programmatically but I hope I will in a day or two. Also please note that in this last attempt, API and UI seem to agree about users being default locked out unlike when we tried to seed users before. Will report back once we have been able to try out that again with you updated code above. Thanks.

improwise commented 2 months ago
result = await _identityUserManager.SetLockoutEnabledAsync(identityUser, false)
result = await _identityUserManager.SetLockoutEndDateAsync(identityUser, null)

Tried this out now and as expected, all users are created with LockoutEnabled=true regardless of if you do it in code or in the UI. This is true also for the admin user and you can se that in the database as well, so it isn't a business layer problem. The admin user seem to work though even though it is set to lockout. So unless the idea is that all created users should be locked out by default, there seem to be a problem here.

SetLockoutEnabledAsync() seems to work though so it is possible to seed users if you do that extra step.

improwise commented 2 months ago

@maliming Any news on this? Thanks.

maliming commented 2 months ago

hi

I will check and fix this.

maliming commented 2 months ago

hi

The Account lockout means enabling Lockout for this user so you can lock/unlock it.

I will update the property description to make it more clear.

https://github.com/abpframework/abp/pull/20274