Activities of "maliming"

Hi,

Both advisories are fixed in lodash 4.18.0+. @abp/lodash already allows any 4.x ("lodash": "^4.17.21"), so you can force the safe version in your own project right now:

  1. Add a resolution in your root package.json (use overrides for npm/pnpm):
{
  "resolutions": {
    "lodash": "^4.18.1"
  }
}
  1. Re-install and refresh the libs folder:
yarn install
abp install-libs

abp install-libs copies the physical files from node_modules into wwwroot/libs, so once lodash is bumped there, your wwwroot/libs/lodash/lodash.min.js will be the patched version and both advisories should clear.

We'll also raise the floor in @abp/lodash for future releases.

Thanks

Your current question has been refunded.

Thanks.

Hi,

Great to hear the workaround is working for you. The fix is queued for 10.2.2, so once you move to that version you can drop the two custom pages.

On managing tenant users from the host: right now the Users page is always scoped to the current tenant, so you have to be signed in as a tenant admin to edit / disable / delete users of that tenant.

Thanks again for the detailed logs and HAR on the 2FA issue — that helped a lot.

Thanks

: )

Hi,

Thanks for the log and HAR — with the password correct this time, the flow tells the full story:

[INF] AuthenticationScheme: Identity.TwoFactorUserId signed in.          ← login wrote the 2FA cookie
[INF] Executed handler method OnPostAsync, returned RedirectToPageResult
[INF] Redirecting to ./SendSecurityCode.
[INF] POST /Account/Login - 302

[INF] Executing handler method SendSecurityCodeModel.OnGetAsync
[INF] Executed handler method OnGetAsync, returned RedirectToPageResult  ← bounced back
[INF] Redirecting to ./Login.
[INF] GET /Account/SendSecurityCode - 302

We've reproduced and confirmed this is a real bug in Account.Pro when Shared mode is combined with 2FA. Here's exactly what happens:

  1. On login, FindSharedUserByNameAsync locates the user across tenants. If the user row only lives under a tenant (no TenantId IS NULL row in AbpUsers), it returns the tenant user. The password check succeeds, 2FA is required, and ASP.NET Core Identity writes the .AspNetCore.Identity.TwoFactorUserId cookie. That cookie, by design of AspNetCore Identity, only carries the UserId — no TenantId.
  2. On the follow-up GET /Account/SendSecurityCode the user isn't authenticated yet, so AbpAccountTenantResolveContributor (Shared mode) short-circuits CurrentTenant to null.
  3. SendSecurityCode.OnGetAsync calls SignInManager.GetTwoFactorAuthenticationUserAsync(), which internally calls UserManager.FindByIdAsync(userId). That call goes through the default EF IMultiTenant filter (WHERE TenantId IS NULL), so the tenant-owned user row is filtered out, the method returns null, and the page redirects back to /Account/Login.

Non-2FA accounts don't hit this because they complete the login in a single POST and get the full Identity.Application cookie (which does carry TenantId), so no tenant context is ever lost.

We'll fix this in 10.2.2. In the meantime, as a drop-in workaround on your side, override the two affected Razor Pages in your Blazor host project. The overrides disable the IMultiTenant filter while fetching the 2FA user, then switch CurrentTenant to the user's tenant for the rest of the handler. I compiled both files against the 10.2 Volo.Abp.Account.Pro.Public.Web assembly to make sure they build cleanly:

using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Volo.Abp.Account;
using Volo.Abp.Account.Public.Web.Pages.Account;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;

namespace YourProject.Web.Pages.Account;

[ExposeServices(typeof(SendSecurityCodeModel))]
public class CustomSendSecurityCodeModel : SendSecurityCodeModel
{
    [UnitOfWork]
    public override async Task<IActionResult> OnGetAsync()
    {
        var dataFilter = LazyServiceProvider.LazyGetRequiredService<IDataFilter>();

        Volo.Abp.Identity.IdentityUser user;
        using (dataFilter.Disable<IMultiTenant>())
        {
            user = await SignInManager.GetTwoFactorAuthenticationUserAsync();
        }

        if (user == null)
        {
            return RedirectToPage("./Login");
        }

        using (CurrentTenant.Change(user.TenantId))
        {
            Providers = (await AccountAppService.GetTwoFactorProvidersAsync(new GetTwoFactorProvidersInput
            {
                UserId = user.Id,
                Token = await UserManager.GenerateUserTokenAsync(user, TokenOptions.DefaultProvider,
                    nameof(Microsoft.AspNetCore.Identity.SignInResult.RequiresTwoFactor))
            })).Select(userProvider => new SelectListItem
            {
                Text = userProvider,
                Value = userProvider
            }).ToList();
        }

        return Page();
    }

    [UnitOfWork]
    public override async Task<IActionResult> OnPostAsync()
    {
        var dataFilter = LazyServiceProvider.LazyGetRequiredService<IDataFilter>();

        Volo.Abp.Identity.IdentityUser user;
        using (dataFilter.Disable<IMultiTenant>())
        {
            user = await SignInManager.GetTwoFactorAuthenticationUserAsync();
        }

        if (user == null)
        {
            return RedirectToAction("Login");
        }

        using (CurrentTenant.Change(user.TenantId))
        {
            return await base.OnPostAsync();
        }
    }
}
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp;
using Volo.Abp.Account.Public.Web.Pages.Account;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Security.Claims;
using Volo.Abp.Uow;

namespace YourProject.Web.Pages.Account;

[ExposeServices(typeof(VerifySecurityCodeModel))]
public class CustomVerifySecurityCodeModel : VerifySecurityCodeModel
{
    public CustomVerifySecurityCodeModel(ICurrentPrincipalAccessor currentPrincipalAccessor)
        : base(currentPrincipalAccessor)
    {
    }

    [UnitOfWork]
    public override async Task OnGetAsync()
    {
        var dataFilter = LazyServiceProvider.LazyGetRequiredService<IDataFilter>();

        Volo.Abp.Identity.IdentityUser user;
        using (dataFilter.Disable<IMultiTenant>())
        {
            user = await SignInManager.GetTwoFactorAuthenticationUserAsync();
        }

        if (user == null)
        {
            throw new UserFriendlyException(L["VerifySecurityCodeNotLoggedInErrorMessage"]);
        }

        using (CurrentTenant.Change(user.TenantId))
        {
            IsRememberBrowserEnabled = await IsRememberBrowserEnabledAsync();
        }
    }

    [UnitOfWork]
    public override async Task<IActionResult> OnPostAsync()
    {
        var dataFilter = LazyServiceProvider.LazyGetRequiredService<IDataFilter>();

        Volo.Abp.Identity.IdentityUser user;
        using (dataFilter.Disable<IMultiTenant>())
        {
            user = await SignInManager.GetTwoFactorAuthenticationUserAsync();
        }

        if (user == null)
        {
            return RedirectToPage("./Login");
        }

        using (CurrentTenant.Change(user.TenantId))
        {
            return await base.OnPostAsync();
        }
    }
}

Drop both files into your Blazor host project (any namespace is fine, the [ExposeServices] attribute tells ABP's DI to replace the built-in pages). No Startup / Module changes needed. Please give it a try and let me know if 2FA login works end-to-end for you.

Thanks

Hi,

Got your log and HAR, thanks. The good news is this isn't a 2FA bug — the login never actually reaches the 2FA step. The log shows a plain password mismatch for user tony:

[INF] Executing handler method Volo.Abp.Account.Public.Web.Pages.Account.LoginModel.OnPostAsync
...
[DBG] Invalid password for user.
[INF] Executed handler method OnPostAsync, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
[INF] Request finished HTTP/2 POST .../Account/Login - 200 null text/html

The HAR confirms it from the browser side:

  • Only one request to /Account/* in the whole capture — POST /Account/Login returning 200 (no redirect, no Location header).
  • No request to /Account/SendSecurityCode at all.
  • No .AspNetCore.Identity.TwoFactorUserId cookie is ever set in any response.
  • The response HTML contains the standard error alert rendered by the Login page:
<div role="alert" class="alert alert-danger alert-dismissible fade show">
    Invalid username or password!
</div>

So what you're seeing as "redirect back to login" is actually the Login page re-rendering itself with the Invalid username or password alert after SignInManager.PasswordSignInAsync returned SignInResult.Failed. The RequiresTwoFactor branch is never hit, which is why you never see the 2FA screen.

My guess on why this correlates with 2FA-enabled accounts: shared-mode user lookup prefers the host user when multiple matches exist. If your 2FA-enabled users were created/migrated in a way that left a different password hash on the host row vs the tenant row, the shared-mode login will now check against the host row — and the password you remember (set on the tenant row) won't match.

Could you try the following and let me know:

  1. Sign in as an admin and reset tony's password from the host Identity Users page (make sure you're viewing Host users, not a tenant). Then try logging in with the new password.
  2. If that works and you land on the 2FA screen, we've confirmed it's a stale host password from the shared-mode migration.
  3. If it still fails after a host-side password reset, send me the new debug log + HAR of that attempt and we'll dig further.

Thanks

Refunded

Hi,

Elsa Studio is a UI project that can be used in Blazor Server and WASM projects. It can be viewed as a standalone project, and currently it is still challenging to fully integrate it into our own project.

Elsa has its own user/role/tenant system, and it is different from ABP:

  • Elsa has its own Tenant entity, ITenantStore, ITenantsProvider, ITenantResolver, and /tenants CRUD endpoints.
  • Elsa entities use string? TenantId, but ABP uses Guid?.
  • Elsa reads the tenant from the http://schemas.microsoft.com/identity/claims/tenantid claim (CustomClaimTypes.TenantId), which is not the same claim name that ABP writes by default.

So all Elsa permissions in AbpElsaPermissionDefinitionProvider are registered as MultiTenancySides.Host for now, and the elsa-pro.md doc also says the module is "not yet fully integrated".

Tenant users logging into Elsa Studio to manage their own workflows is not supported yet. To make it work properly we need a mapping layer between ABP tenants and Elsa tenants, write the Elsa tenant claim to the token, open the permissions to the Tenant side, and optionally bridge ABP's tenant connection string to Elsa's Tenant.Configuration for per-tenant workflow databases.


For now, the suggested way to use the module is:

  • Keep the workflow definitions on the Host side and let only host admins log in to Elsa Studio.
  • Pass TenantId into the workflow as an input/variable, and let the workflow branch on it when needed.
  • In your custom activities, use ICurrentTenant.Change(tenantId) to switch to the target tenant before calling any ABP service (repositories, managers, email, etc.).
  • Trigger workflows from ABP distributed events. ABP events already carry the TenantId, so the workflow naturally runs in the context of the right tenant. This is the same pattern used in the ElsaDemoApp sample.

This way a single set of workflow definitions can serve all tenants, and you don't need to work around the multi-tenancy limitation on the Elsa side.


We have already seen the 3.6.0 changes on the Elsa side: TenantsOptions.IsEnabled, "" as the default tenant id, null as tenant-agnostic, the TenantDeleted event, tenant id added to the stored trigger index, etc. These are good improvements, but the multi-tenancy model on the Elsa side is still moving. If we build the integration right now, we will likely have to redo parts of it after the next change on their side.

We will keep the Host-only setup for now, and do a proper multi-tenant integration once Elsa's multi-tenancy is stable. We will update the module and the docs at that time.

Thanks

hi

We fixed it. Can you try again?

Thanks.

hi

Yes, You have to enable the Web Socket feature.

Thanks.

Showing 591 to 600 of 12928 entries
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 November 02, 2026, 06:56
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.