Open Closed

Volo.Abp.BusinessException occuring when turning on 2FA for a user #8928


User avatar
0
balessi75 created

ABP Commercial 7.4.2 / Blazor Server / EF / Non tiered / Separate Host and Tenant DBs / Lepton Theme

We have a customer that added users with the tenant setting for 2FA setup as 'Optional'. The customer then updated the tenant setting for 2FA to be 'Forced'. There are now users without 2FA setup while 2FA is setup to be 'Forced' at the tenant level. When logged in as the admin, and the customer attempts to turn on 2FA for a user, the below exception occurs. When changing the tenant 2FA setting back to 'Optional', the user setting for 2FA can saved/toggled without an exception.

How can we work around this issue?

2025-03-07 19:16:45.732 +00:00 [WRN] (Instance: 8235) Unhandled exception rendering component: Exception of type 'Volo.Abp.BusinessException' was thrown.
Volo.Abp.BusinessException: Exception of type 'Volo.Abp.BusinessException' was thrown.
   at Volo.Abp.Identity.IdentityUserAppService.SetTwoFactorEnabledAsync(Guid id, Boolean enabled)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous(IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapter.ProceedAsync()
   at Volo.Abp.Authorization.AuthorizationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous(IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapter.ProceedAsync()
   at Volo.Abp.GlobalFeatures.GlobalFeatureInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous(IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapter.ProceedAsync()
   at Volo.Abp.Auditing.AuditingInterceptor.ProceedByLoggingAsync(IAbpMethodInvocation invocation, AbpAuditingOptions options, IAuditingHelper auditingHelper, IAuditLogScope auditLogScope)
   at Volo.Abp.Auditing.AuditingInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous(IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapter.ProceedAsync()
   at Volo.Abp.Features.FeatureInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous(IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapter.ProceedAsync()
   at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous(IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapter.ProceedAsync()
   at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Volo.Abp.Identity.Pro.Blazor.Pages.Identity.UserManagement.ChangeTwoFactorAsync()
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Volo.Abp.BlazoriseUI.Components.SubmitButton.OnClickedHandler()
   at Volo.Abp.BlazoriseUI.Components.SubmitButton.OnClickedHandler()
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Blazorise.Button.ClickHandler(MouseEventArgs eventArgs)
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
2025-03-07 19:16:45.732 +00:00 [ERR] (Instance: 8235) Unhandled exception in circuit 'xwvskV5PTwMavvvHpRq1MyaxOXSC3Nzyyc_KtxNoG_c'.
Volo.Abp.BusinessException: Exception of type 'Volo.Abp.BusinessException' was thrown.
   at Volo.Abp.Identity.IdentityUserAppService.SetTwoFactorEnabledAsync(Guid id, Boolean enabled)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous(IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapter.ProceedAsync()
   at Volo.Abp.Authorization.AuthorizationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous(IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapter.ProceedAsync()
   at Volo.Abp.GlobalFeatures.GlobalFeatureInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous(IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapter.ProceedAsync()
   at Volo.Abp.Auditing.AuditingInterceptor.ProceedByLoggingAsync(IAbpMethodInvocation invocation, AbpAuditingOptions options, IAuditingHelper auditingHelper, IAuditLogScope auditLogScope)
   at Volo.Abp.Auditing.AuditingInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous(IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapter.ProceedAsync()
   at Volo.Abp.Features.FeatureInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous(IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapter.ProceedAsync()
   at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous(IInvocation invocation, IInvocationProceedInfo proceedInfo)
   at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapter.ProceedAsync()
   at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
   at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
   at Volo.Abp.Identity.Pro.Blazor.Pages.Identity.UserManagement.ChangeTwoFactorAsync()
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Volo.Abp.BlazoriseUI.Components.SubmitButton.OnClickedHandler()
   at Volo.Abp.BlazoriseUI.Components.SubmitButton.OnClickedHandler()
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Blazorise.Button.ClickHandler(MouseEventArgs eventArgs)
   at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)

17 Answer(s)
  • User Avatar
    0
    balessi75 created

    2fa-exception.PNG

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    I will hide the 2FA menu from user dropbox if the current behavior is Forced,

    or show the message details: It's not allowed to change two factor setting.

    Thanks.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    We have fixed this in 9.0 version

    Here is the changes:

    image.png

    385638665-a945c213-54cb-4e86-a00d-ad2f4ab7ee52.gif

  • User Avatar
    0
    balessi75 created

    Thanks.

    If I change the tenant's 2FA setting to 'Forced', the user cannot turn on/off their 2FA under their profile which makes sense. but if the user had 2FA turned off on their profile and the tenant setting is now set to 'Forced', shouldn't the user have to perform 2fa to login in? This user has a 2fa provider setup for email.

    In order to make this work, we had to set the tenant 2FA setting back to 'Optional' then turn on 2FA for the user, then set the tenant back to 'Forced'

    Is there something we are missing here? shouldn't all users be required to do 2fa if it is setup as 'Forced' on the tenant level (regardless of what the setting is on the user level)?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    If you set 2FA to Forced, The system will assume all users have 2FA enabled, but they need to configure at least one valid 2FA provider. eg: email. SMS, authenticator.

  • User Avatar
    0
    balessi75 created

    in our system all users self-register and when the tenant is set to have 2fa Forced, all newly registered users get created with 2fa turned off, so in essence 2fa is never forced. so this means an admin has to manually visit each user to turn on 2fa?

    Additionally, in our system all users will always have a verified email for use in 2fa.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Does your system user have at least one valid 2FA provider? eg they confirmed their email address.

    I think if they have. After setting 2FA to Force, every user must log in with 2FA.

  • User Avatar
    0
    balessi75 created

    Yes, every user has a confirmed email, but 2fa isn't enforced because its turned off at the user level.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Can you test it in a new template project?

    I have checked the source code. the logic is no problem

    image.png

  • User Avatar
    0
    balessi75 created

    I'm trying to create a new project from the template and I'm getting the following when clicking on the login link.. I already ran yarn and abp install-libs from the solution folder.

    An unhandled exception occurred while processing the request.
    AbpException: Could not find the bundle file '/libs/bootstrap/js/bootstrap.enable.tooltips.everywhere.js' for the bundle 'Lepton.Global'!
    Volo.Abp.AspNetCore.Mvc.UI.Bundling.TagHelpers.AbpTagHelperResourceService.ProcessAsync(ViewContext viewContext, TagHelper tagHelper, TagHelperContext context, TagHelperOutput output, List<BundleTagHelperItem> bundleItems, string bundleName)

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    What is your project package version? abp and leptonx?

    Did you use Studio to create the new project?

    Thanks

  • User Avatar
    0
    balessi75 created

    I used abp suite to create the application it is using Lepton theme at version 7.2.1. I ran install-libs from the ProjectName.Blazor folder.

    {
      "version": "1.0.0",
      "name": "my-app",
      "private": true,
      "dependencies": {
        "@volo/abp.aspnetcore.components.server.leptontheme": "7.2.1",
        "@volo/abp.aspnetcore.mvc.ui.theme.lepton": "7.2.1",
        "@volo/account": "~7.2.1",
        "@volo/cms-kit-pro.admin": "~7.2.1",
        "@volo/language-management": "~7.2.1"
      }
    }
    
    
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Please share your project with liming.ma@volosoft.com

    I will download and check it.

    Thanks.

  • User Avatar
    0
    balessi75 created

    Hi

    I emailed you a link to the project solution.

  • User Avatar
    0
    balessi75 created

    Hi,

    I was able to get the template solution to work and found that I could not replicate the two factor issue. So it is unclear to me why we are seeing the issue in our solution.

    To debug, I overrode GetTwoFactorEnabledAsync in the IdentityProUserStore and found that when it runs, it correctly returns true because the tenant's 2fa setting is set to forced.

    Our override to the login process relative to 2fa is not changed from the original ABP implementation...

            var result = await SignInManager.PasswordSignInAsync(
                LoginInput.UserNameOrEmailAddress,
                LoginInput.Password,
                LoginInput.RememberMe,
                true
            );
    
            await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext
            {
                Identity = IdentitySecurityLogIdentityConsts.Identity,
                Action = result.ToIdentitySecurityLogAction(),
                UserName = LoginInput.UserNameOrEmailAddress
            });
    
            if (result.RequiresTwoFactor)
            {
                return RedirectToPage("./SendSecurityCode", new {
                    returnUrl = ReturnUrl,
                    returnUrlHash = ReturnUrlHash,
                    rememberMe = LoginInput.RememberMe,
                    linkUserId = LinkUserId,
                    linkTenantId = LinkTenantId,
                    linkToken = LinkToken
                });
            }
    

    result.RequiresTwoFactor returned from await SignInManager.PasswordSignInAsync returns false.

  • User Avatar
    0
    balessi75 created

    Thank you for your help maliming.

    Once I cleared my cookies everything worked as expected.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Great

Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
Do you need assistance from an ABP expert?
Schedule a Meeting
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v9.2.0-preview. Updated on March 13, 2025, 04:08