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)
-
0
-
0
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.
-
0
hi
We have fixed this in 9.0 version
Here is the changes:
-
0
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)?
-
0
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. -
0
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.
-
0
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. -
0
Yes, every user has a confirmed email, but 2fa isn't enforced because its turned off at the user level.
-
0
hi
Can you test it in a new template project?
I have checked the source code. the logic is no problem
-
0
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) -
0
What is your project package version? abp and leptonx?
Did you use Studio to create the new project?
Thanks
-
0
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" } }
-
0
-
0
Hi
I emailed you a link to the project solution.
-
0
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 theIdentityProUserStore
and found that when it runs, it correctly returnstrue
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 fromawait SignInManager.PasswordSignInAsync
returns false. -
0
Thank you for your help maliming.
Once I cleared my cookies everything worked as expected.
-
0
Great