Hi,
One quick clarification on the Authorization failed lines you pasted earlier — those are not coming from ABP's standard permission system.
ABP's permission checks go through PermissionRequirement (created by AbpAuthorizationPolicyProvider), and a failing ABP permission check would log as:
Authorization failed. These requirements were not met:
PermissionRequirement: DCOT.AttestationAlerts
What you're seeing is:
ClaimsAuthorizationRequirement:Claim.Type=DCOT.AttestationAlerts and Claim.Value is one of the following values: (true)
ClaimsAuthorizationRequirement is ASP.NET Core's built-in type produced by policy.RequireClaim(...). It doesn't come from ABP — it's produced by hand-written AddAuthorization code somewhere in your solution.
The DCOT.AttestationAlerts / DCOT.AttestationAlerts.Edit / DCOT.PageSnapshots names are almost certainly ABP permission names (ABP writes granted permissions into the principal as claims — claim type = permission name, value = "true" — via IAbpClaimsPrincipalContributor). But the fact that they're checked with ClaimsAuthorizationRequirement (all three in one policy) tells us there's a custom policy built like this somewhere in your code:
services.AddAuthorization(options =>
{
options.AddPolicy("SomePolicyName", policy =>
policy.RequireClaim("DCOT.AttestationAlerts", "true")
.RequireClaim("DCOT.AttestationAlerts.Edit", "true")
.RequireClaim("DCOT.PageSnapshots", "true"));
// If the same policy is also assigned as the fallback, every endpoint without
// an explicit [AllowAnonymous] will go through it — including /Account/SendSecurityCode
options.FallbackPolicy = options.GetPolicy("SomePolicyName");
});
If that policy is set as FallbackPolicy / DefaultPolicy, or applied via Razor Pages conventions (AuthorizeFolder / AuthorizePage), it will kick in on /Account/SendSecurityCode too. A 2FA-mid-flow user only holds the TwoFactorUserIdScheme cookie, which does not carry those DCOT.* claims — so the page gets rejected and ASP.NET Core redirects the browser back to /Account/Login. That's a perfect match for your symptom (login → straight back to login, no 2FA screen), and it also explains why non-2FA accounts work (they get the full application cookie with all claims in a single POST, so they pass the fallback policy on subsequent requests).
Could you please search your solution for:
services.AddAuthorization(options => ...) or Configure<AuthorizationOptions>(options => ...) blocks — especially anything setting FallbackPolicy or DefaultPolicy.RequireClaim("DCOT.AttestationAlerts"...), RequireClaim("DCOT.PageSnapshots"...) usages.Configure<RazorPagesOptions>(options => options.Conventions.AuthorizeFolder(...)) / AuthorizePage(...) that pulls in that policy.Share the snippets you find and we'll pinpoint the fix. If it is a fallback policy, the fix is usually either to scope the policy to specific endpoints (e.g. your API controllers via [Authorize("SomePolicyName")]) instead of using FallbackPolicy, or to explicitly allow /Account/* through.
Alongside the config, the full debug log for one failing login attempt from POST /Account/Login until the browser ends up back on /Account/Login is still the other thing we really need — the snippet you sent before only covered the login page rendering (GETs for JS files), not the actual POST + redirect chain.
Thanks
hi
We will check and fix it
Thanks.
hi
I sent the code.
Thanks.
hi
Could you send an email to liming.ma@volosoft.com?
I'll share the source code with you. The next version of the CLI will let you download it.
Thanks.
hi
We will fix it today. I will let you know. Sorry about the delay.
ok. Let's move to the https://abp.io/support/questions/10603/Duplicating-rendered-select-drop-down-controls-in-Razor-MVC-after-upgrade-to-102#answer-3a20b244-5b79-9d23-190c-8f536dbfb7aa
Thanks.
Hi,
The RMG020 warning is actually expected behavior from Mapperly. By default Mapperly uses RequiredMappingStrategy.Both, meaning every source member is expected to be mapped to a target member (and vice versa). When you map an entity like Department (which inherits ABP audit fields like TenantId, CreationTime, CreatorId, IsDeleted, LastModificationTime, etc.) to a leaner DTO such as DepartmentExcelDto, every extra source field will trigger RMG020. That's why you see 6k+ warnings piling up in one file.
The fix is to tell Mapperly to only require the target members to be mapped. Just add RequiredMappingStrategy = RequiredMappingStrategy.Target to your [Mapper] attribute:
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class DemoApplicationMappers
{
public partial DepartmentExcelDto DepartmentToDepartmentExcelDto(Department source);
// ... your other mappings
}
This one-line change will silence all of those RMG020 warnings at once, and still keeps the useful warnings (when a target property is missing a mapping).
If you have several mapper classes and want to set it once for the whole project, you can drop this into any .cs file instead of repeating the attribute on every class:
[assembly: MapperDefaults(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
This is exactly how ABP's own modules and the latest ABP Studio solution templates are set up. Every generated mapper ships with RequiredMappingStrategy = RequiredMappingStrategy.Target and inherits from MapperBase<TSource, TDestination>, e.g.:
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class DepartmentToDepartmentExcelDtoMapper : MapperBase<Department, DepartmentExcelDto>
{
public override partial DepartmentExcelDto Map(Department source);
public override partial void Map(Department source, DepartmentExcelDto destination);
}
You can check the official migration guide for more context and examples:
https://abp.io/docs/latest/release-info/migration-guides/automapper-to-mapperly
Thanks
ok, no problem. : )
hi
We will add it to the download modules list.
Thanks.
Hi,
Since you're on 10.2+, shared accounts should already ship with AbpAccountTenantResolveContributor that forces CurrentTenant = null during the 2FA flow (because the user is not yet fully authenticated when entering the 2FA code). So in theory the 2FA page should look up the host user and work fine.
Before I dig deeper, a few questions to narrow it down — could you check and share:
How do you resolve tenants? Especially: are you using domain / subdomain tenant resolution (e.g. tenant1.mydomain.com)? If yes, please share the related configuration (where you call options.Tenants, AddDomainTenantResolver, or anything that inserts a domain/subdomain contributor). If you inserted it before CurrentUserTenantResolveContributor, that will bypass the shared-mode guard above and CurrentTenant will be set to the tenant on the 2FA page, which breaks GetTwoFactorAuthenticationUserAsync.
Confirm UserSharingStrategy — please share your Configure<AbpMultiTenancyOptions>(...) block from staging. Staging and local may not be on the same configuration:
Configure<AbpMultiTenancyOptions>(options =>
{
options.IsEnabled = true;
options.UserSharingStrategy = TenantUserSharingStrategy.Shared;
});
What is the login URL on staging? Is it the host domain, a tenant subdomain, or a dedicated account domain? And what about local?
Browser DevTools check — reproduce the issue on staging, then in DevTools → Application → Cookies, check:
.AspNetCore.Identity.TwoFactorUserId cookie written after you submit username/password?/Account/SendSecurityCode, is that cookie sent back in the request headers?Domain / SameSite / Secure differences vs. local?Debug logs from the failing request on staging — please temporarily enable Debug level logs and capture the logs from the moment you submit the login form until you get redirected back to the login page. See this guide: https://abp.io/support/questions/8622/How-to-enable-Debug-logs-for-troubleshoot-problems
CurrentTenant.Id values, any CheckCurrentTenant failures (e.g. ApplicationException: Current tenant is different than given tenant. CurrentTenant.Id: ..., given tenantId: ...), SignInManager/TwoFactor related log entries, and any warnings/exceptions around the redirect.Does this happen for every 2FA account on staging, or only some of them? And does a pure host user (not in any tenant) with 2FA work on staging?
My current suspicion is either (a) a domain/subdomain tenant resolver inserted before the shared-mode guard, or (b) a cookie issue (SameSite/Domain) on staging that loses the TwoFactorUserId cookie across the redirect. The debug logs + the answers above should tell us which one.
Thanks