Open Closed

Shared Accounts from Tenants - duplicate username #10619


User avatar
0
Buckoge created

Hi,

First of all, this is a great feature β€” thank you πŸ™‚

I created two tenants (with separate databases) using the same username (admin) for testing purposes, and the system allowed this.

However, during authentication, only the account associated with the first created tenant can be accessed successfully. Attempts to log in with the second tenant result in the error message: "Invalid username or password."

In the AbpUsers table (Host side), two users are created with the same username but different email addresses.

According to the documentation for Shared User Accounts, username and email uniqueness should be enforced globally. However, in this case, the system allows duplicate usernames across tenants.

After a user clicks on the invitation link and chooses a username, there does not appear to be any validation preventing duplicates.

Could you please verify whether this behavior is expected, a configuration issue, or a potential bug?

This is not urgent for us, as we are not in production yet. I was just testing this functionality and wanted to share the result i got.

For reference, I have added the following in the Domain module:

Configure<AbpMultiTenancyOptions>(options =>
{
    options.IsEnabled = true;
    options.UserSharingStrategy = TenantUserSharingStrategy.Shared;
});

Thanks.

Markdown supported.
Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)

5 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    • With TenantUserSharingStrategy.Shared, username/email must be globally unique (Host + all tenants). So having two different users with the same UserName = admin is not expected in a correctly working Shared User Accounts setup.
    • The symptom you see during login (β€œonly the first tenant’s admin works; the other returns Invalid username or password”) is consistent with this: the login flow (host-side) resolves a user by username/email, finds the first matching β€œadmin”, then password verification is performed for that user. If the password you typed belongs to the other β€œadmin” record, it fails and you get β€œInvalid username or password”.

    What to do (verified, definitive)

    1. Do not seed/create β€œadmin” separately per tenant when using Shared strategy.

      • In Shared mode, the recommended flow is:
        1. Create tenant
        2. Invite an existing global user (or let them register from invitation)
        3. Assign roles in that tenant
      • If you created tenants in a way that auto-creates a tenant-local admin user (classic isolated behavior), you can end up with conflicting global identities.
    2. Fix your current data

      • In the Host database, ensure there is only one AbpUsers record for a given UserName (and also uniqueness across emails).
      • Then associate that single global user with multiple tenants via the Shared User Accounts invitation/association mechanism (rather than having separate β€œadmin” users).
    3. Re-test using invitations

      • Create a single global user (e.g., admin) once.
      • Invite that user into tenant A and tenant B.
      • On login, ABP should authenticate once and then (if user belongs to multiple tenants) show a tenant selection step.

    Conclusion

    This behavior is not expected under Shared User Accounts; it indicates your tenants were created/seeded in a way that produced duplicate global identities (two different host users with the same username). The correct approach is one user globally + tenant associations, not β€œone admin per tenant”.

    • https://abp.io/docs/latest/modules/account/shared-user-accounts
    • https://abp.io/community/articles/mf3bkg79

    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer β€” our support team will jump in to help you soon.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    Buckoge created

    Ok, I forgot to mention that all of this was done using the SaaS module manually.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    You're right, this is a problem. The invite-accept path didn't run the global username/email uniqueness check in shared mode, so two different invitees could each claim admin in their tenant. Host AbpUsers ended up with duplicate rows and login can only resolve the first one, which is why the second tenant's admin can't sign in.

    Until the fix ships in 10.2.2 / 10.3.1 you can either give each tenant's admin a unique username (e.g. admin-tenant1 / admin-tenant2), or drop this UserSharingManager override into your Domain module to reject the duplicate right now:

    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(UserSharingManager))]
    public class MyUserSharingManager : UserSharingManager
    {
        public MyUserSharingManager(
            IOptions<AbpMultiTenancyOptions> multiTenancyOptions,
            IDataFilter dataFilter,
            ITenantStore tenantStore,
            IdentityProUserManager userManager,
            IIdentityUserRepository userRepository,
            IdentityRoleManager roleManager,
            IIdentityRoleRepository roleRepository,
            UserInvitationManager userInvitationManager,
            IAbpDistributedLock distributedLock)
            : base(multiTenancyOptions, dataFilter, tenantStore, userManager, userRepository, roleManager, roleRepository, userInvitationManager, distributedLock)
        {
        }
    
        public override async Task AcceptInviteAsync(Guid invitationId, string username, string password, string passwordHash)
        {
            if (IsEnabled())
            {
                var invitation = await UserInvitationManager.GetAsync(invitationId);
                if (invitation.Status == UserInvitationStatus.Pending)
                {
                    var hostUsersWithUserName = await GetUsersByUserNameFromHostAsync(username, includeLeaved: true);
                    if (hostUsersWithUserName.Any(x => !string.Equals(x.Email, invitation.InviteeEmail, StringComparison.OrdinalIgnoreCase)))
                    {
                        throw new BusinessException(IdentityProErrorCodes.InviteUserUserNameAlreadyExists).WithData("UserName", username);
                    }
    
                    var hostUsersWithEmail = await GetUsersByEmailFromHostAsync(invitation.InviteeEmail, includeLeaved: true);
                    if (hostUsersWithEmail.Any(x => !string.Equals(x.UserName, username, StringComparison.OrdinalIgnoreCase)))
                    {
                        throw new BusinessException(IdentityProErrorCodes.InviteUserEmailAlreadyExists).WithData("Email", invitation.InviteeEmail);
                    }
                }
            }
    
            await base.AcceptInviteAsync(invitationId, username, password, passwordHash);
        }
    }
    

    If you already have duplicate rows in host AbpUsers from testing, delete one or rename its UserName so login can disambiguate.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    Buckoge created

    Hi,

    Thank you for the explanation.

    I came across this while testing and wasn’t sure of the best place to report it, so i decided to share it here. As mentioned earlier, we are still in the pre-production phase, so we’re happy to wait for the fix in the upcoming release.

    Thanks again, glad i could help πŸ™‚

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    Thanks for catching this during testing β€” really appreciate it, that kind of feedback before production saves us a lot of pain. The fix will land in the next release, so you can grab it from there.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❀️ on ABP v10.8.0-preview. Updated on September 28, 2026, 11:44
1
ABP Assistant
πŸ” You need to be logged in to use the chatbot. Please log in first.