Activities of "AI-Bot"

Answer
  • Your 502 after redirect is consistent with “response header too large” scenarios on Azure App Service / reverse proxies when the authentication cookie grows beyond typical limits (often ~8KB per cookie).
  • In your configuration, the single biggest contributor to cookie bloat is:
options.SaveTokens = true;

With SaveTokens = true, ASP.NET Core stores tokens (id_token/access_token/refresh_token if present) inside the authentication cookie (.AspNetCore.Cookies / Identity cookie). With Okta, these tokens can easily push the cookie over 8KB.

What to change (reduce cookie size)

  1. Disable token saving Change your Okta OpenID Connect configuration to:
options.SaveTokens = false;

This alone typically drops the cookie size dramatically.

  1. Keep/confirm Dynamic Claims is not the reason app.UseDynamicClaims() and:
options.IsDynamicClaimsEnabled = true;

are about refreshing claims per-request; they are not meant to inflate the cookie. The cookie still initially contains the claims created at sign-in, but ABP can override them dynamically afterward. So the primary fix here is still SaveTokens = false.

  1. (Optional) If you still need tokens, don’t store them in the auth cookie If some part of your app needs Okta tokens, store them server-side (e.g., DB/distributed cache) keyed by user/session, instead of SaveTokens=true. (There isn’t an ABP-specific “shrink cookie” switch that safely compresses/encrypts tokens into fewer bytes—tokens are already compact JWT strings and will bloat cookies if stored there.)

Sources

  • ABP Dynamic Claims docs (to confirm what dynamic claims does/doesn’t do):
    https://abp.io/docs/latest/framework/fundamentals/dynamic-claims
  • ASP.NET Core cookies overview (background on cookie-based auth and why large cookies break behind proxies):
    https://learn.microsoft.com/aspnet/core/security/authentication/cookie?view=aspnetcore-9.0

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.

Answer
  • AddVirtualJson(...) is correct, but it only works if your JSON files are actually available in ABP Virtual File System at runtime.
  • The most common reason it “works in Debug but not in your app / not at all” is that the vi.json files are not embedded (or not added to VFS), so ABP can’t find them. Then ABP keeps using the module’s built-in en.json.

Use this checklist (it applies to SaasResource, PaymentResource, AbpIdentityResource, AbpOpenIddictResource):

1) Put the JSON files in the right project and embed them

Place the override files in your *.Domain.Shared project (recommended), e.g.:

MyProject.Domain.Shared
  /Localization
    /AbpIdentity
      vi.json
    /AbpOpenIddict
      vi.json
    /Saas
      vi.json
    /Payment
      vi.json

Then embed them in MyProject.Domain.Shared.csproj:

<ItemGroup>
  <EmbeddedResource Include="Localization\**\*.json" />
  <Content Remove="Localization\**\*.json" />
</ItemGroup>

<ItemGroup>
  <PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="*" />
</ItemGroup>

(Without embedding, the files may not be available in production and ABP won’t load them.)

2) Ensure your Domain.Shared module adds its embedded files to VFS

In your MyProjectDomainSharedModule:

using Volo.Abp.VirtualFileSystem;

Configure<AbpVirtualFileSystemOptions>(options =>
{
    options.FileSets.AddEmbedded<MyProjectDomainSharedModule>();
});

3) Ensure your JSON format is correct (case matters)

Use the standard ABP JSON schema:

{
  "culture": "vi",
  "texts": {
    "SomeKey": "Some Vietnamese value"
  }
}

(culture / texts should be lowercase as above.)

4) Register the virtual json paths (what you already did) in the SAME module that runs

In MyProjectDomainSharedModule:

Configure<AbpLocalizationOptions>(options =>
{
    options.Resources.Get<SaasResource>()
        .AddVirtualJson("/Localization/Saas");

    options.Resources.Get<PaymentResource>()
        .AddVirtualJson("/Localization/Payment");

    options.Resources.Get<AbpIdentityResource>()
        .AddVirtualJson("/Localization/AbpIdentity");

    options.Resources.Get<AbpOpenIddictResource>()
        .AddVirtualJson("/Localization/AbpOpenIddict");
});

Then restart the app (localization is cached).

5) Important: UI language must actually be vi

Even if you set default language to vi, if the current culture is still en, you’ll see English. Make sure Vietnamese exists in AbpLocalizationOptions.Languages and default is vi (or user/tenant sets vi).


If you still see English after doing the above

That typically means either:

  • the keys you’re trying to override belong to a different resource than you think (e.g., AbpAccountResource vs AbpIdentityResource), OR
  • you’re translating texts that are coming from DB dynamic localization (Language Management) rather than JSON resources, in which case this AddVirtualJson approach won’t affect them.

But in your specific snippet (Identity/OpenIddict/SaaS/Payment module UI texts), the usual fix is embedding + AddEmbedded<...>() as above.

Sources:

  • https://abp.io/docs/latest/framework/fundamentals/localization
  • https://abp.io/support/questions/8730
  • https://abp.io/community/articles/ba1oy03l

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.

Answer
  • Add Vietnamese as a supported language.
  • Set Vietnamese as the default language (so ABP modules/UI use vi when there is no user/tenant preference yet).
  • Provide Vietnamese translations for the module resources (either as embedded virtual JSON overriding module resources, or via Language Management DB + the “host fallback” dynamic-localizer approach you already use).

1) Set Vietnamese as the default language + add it to supported languages

In your *.Domain.Shared (or the module where you configure localization), configure AbpLocalizationOptions:

using Volo.Abp.Localization;

Configure<AbpLocalizationOptions>(options =>
{
    // Make sure Vietnamese is available in the language list
    options.Languages.Add(new LanguageInfo(
        "vi",
        "vi",
        "Tiếng Việt",
        flagIcon: "vn"
    ));

    // Make Vietnamese the default when nothing else is selected
    options.DefaultLanguage = "vi";
});

This makes newly created tenants/users start with Vietnamese as the default culture, but it does not automatically translate everything unless Vietnamese resources exist.

2) Provide Vietnamese translations for the ABP module resources (recommended for “default modules”)

ABP module texts come from their own localization resources (embedded JSON). To translate module strings to Vietnamese, you override/extend those resources by adding vi.json under your app and registering it via AddVirtualJson(...) for each module resource you want to override.

Example pattern (same idea as overriding AbpTimingResource in the official article):

using Volo.Abp.Localization;
using Volo.Abp.Timing.Localization;

Configure<AbpLocalizationOptions>(options =>
{
    // Add your overrides for an ABP module resource:
    options.Resources
        .Get<AbpTimingResource>()
        .AddVirtualJson("/Localization/AbpTiming"); // contains vi.json
});

Then create:

  • YourProject.Domain.Shared/Localization/AbpTiming/vi.json

with contents like:

{
  "culture": "vi",
  "texts": {
    "DisplayName:Abp.Timing.Timezone": "Múi giờ",
    "Description:Abp.Timing.Timezone": "Múi giờ của ứng dụng"
  }
}

Repeat this for other module resources you need (Identity, SettingManagement, FeatureManagement, etc.) by adding corresponding folders and vi.json files and registering them with .AddVirtualJson(...).

3) If you want DB-based translations to apply to all tenants

Keep using Language Management + your custom DynamicResourceLocalizer override (host context) so TenantId = null translations are visible to tenants. That ensures newly created tenants also see the translations without copying rows per tenant.


Sources:

  • https://abp.io/docs/latest/framework/fundamentals/localization
  • https://abp.io/community/articles/ba1oy03l

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.

  • With TenantUserSharingStrategy.Shared, the credential verification/login happens on the Host side (global identity). That’s why /connect/token resolves the tenant as Host and why your custom tenant header is not used there. In other words: the password grant is intentionally host-scoped in Shared User Accounts.
  • Therefore, userA must exist in the Host database in a way that the Host-side user lookup can find. In your case, the Host DB row you see for userA has TenantId = <DevTenantId>, so when the token endpoint runs in the Host context (TenantId = null), it won’t match that user and you get “No user found … → invalid_grant”.

Fix (what to do)

  1. Ensure the global (Host-side) user record is created/kept in the Host DB for shared accounts (this is required especially in database-per-tenant setups because Host login can’t query tenant DBs).
  2. After the user can authenticate on Host, they should enter a tenant context using the tenant selection/switch flow (UI does this automatically; for API-only you typically use the switch-tenant extension grant / flow supported by ABP’s Shared Accounts feature rather than trying to pass tenant header to /connect/token).

Answers to your specific questions

  1. Why can’t userA log in?
    Because under Shared accounts, /connect/token authenticates on Host, but the Host-side lookup can’t find userA (your Host DB record is not a Host record; it’s stored with a tenant id).
  2. Is Host record supposed to have TenantId = NULL?
    In ABP’s multi-tenancy model, TenantId = null means Host-owned data. For shared-account login being Host-side, there must be a Host-side user identity to authenticate against. Seeing only a TenantId = Dev record in the Host database explains the behavior you observe.
  3. How is a Shared user supposed to log in to a tenant?
    Not by sending a tenant header to /connect/token. The Shared User Accounts design is: authenticate globally first, then choose/switch the active tenant (tenant selection in UI; switch-tenant flow for programmatic usage).
  4. Does database-per-tenant change any of this?
    Yes: it makes the Host-side record mandatory, because Host authentication cannot “see” tenant databases. Shared strategy relies on having the global identity available at Host (and then associating/syncing to tenant DBs as needed).
  5. Is custom tenant header supported with Shared accounts?
    Custom tenant resolution headers are generally supported by ABP tenant resolvers, but Shared accounts change the intended login flow: /connect/token is Host-side for shared identity, so a tenant header is not the mechanism to select tenant at that stage.

Links (verified):

  • https://abp.io/docs/latest/modules/account/shared-user-accounts
  • https://abp.io/docs/10.3/framework/architecture/multi-tenancy/
  • https://abp.io/docs/10.3/framework/data/entity-framework-core/migrations

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.

Answer
  • In ABP, many UI texts (like DisplayName:Abp.Identity.*, IdentitySettings*, etc.) come from module localization JSON files (embedded en.json, etc.). When a text exists in those JSON resources, ABP can keep returning that value (English) unless your dynamic (DB) localization is configured to override it for the current tenant.
  • Your observation matches a known behavior: DB language texts saved on Host (TenantId = null) may not be visible for tenants, because LanguageText is a multi-tenant entity and the localization lookup/caching runs under the current tenant. So the query is filtered by TenantId = CurrentTenantId, and the Host records are not considered.

To make Host translations apply to all tenants (including newly created ones), replace the dynamic resource localizer so it reads localization texts under the Host context:

using Microsoft.Extensions.Caching.Distributed;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy;

[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(DynamicResourceLocalizer), typeof(IDynamicResourceLocalizer))]
public class MyDynamicResourceLocalizer : DynamicResourceLocalizer
{
    private readonly ICurrentTenant _currentTenant;

    public MyDynamicResourceLocalizer(
        IServiceScopeFactory serviceScopeFactory,
        IDistributedCache<LanguageTextCacheItem> cache,
        ICurrentTenant currentTenant)
        : base(serviceScopeFactory, cache)
    {
        _currentTenant = currentTenant;
    }

    public override LocalizedString GetOrNull(LocalizationResourceBase resource, string cultureName, string name)
    {
        using (_currentTenant.Change(null))
        {
            return base.GetOrNull(resource, cultureName, name);
        }
    }

    protected override LanguageTextCacheItem GetCacheItem(LocalizationResourceBase resource, string cultureName)
    {
        using (_currentTenant.Change(null))
        {
            return base.GetCacheItem(resource, cultureName);
        }
    }

    protected override Task<LanguageTextCacheItem> GetCacheItemAsync(LocalizationResourceBase resource, string cultureName)
    {
        using (_currentTenant.Change(null))
        {
            return base.GetCacheItemAsync(resource, cultureName);
        }
    }
}

And register it (e.g., in your Domain module):

public override void ConfigureServices(ServiceConfigurationContext context)
{
    context.Services.AddSingleton<IDynamicResourceLocalizer, MyDynamicResourceLocalizer>();
}

With this change:

  • You can keep inserting Vietnamese texts into the DB with TenantId = null.
  • Tenants will also resolve those keys from the Host records (so new tenants automatically get the translations).
  • It doesn’t matter if the original English text is defined in embedded JSON; the dynamic localizer will be able to supply the DB value instead.

Links (verified):

  • https://abp.io/support/questions/6636
  • https://abp.io/support/questions/8778

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.

  • Resolve the tenant from a route parameter such as /tenant1 in AuthServer
    1. Use ABP’s route tenant resolver (RouteTenantResolveContributor) by adding the special route parameter name {__tenant} to your routes.
      • For MVC/Razor Pages endpoints on the AuthServer, the pattern is:
[Route("{__tenant}/[controller]")]
       public class MyController : Controller
       {
       }
   or for Razor Pages:
@page "{__tenant?}/Account/Login"
  1. If you want it globally (so you don’t have to edit every page/controller route), you can apply a convention to prepend {__tenant} to all routes (controllers/pages) as shown in the referenced article.
  2. If you also need correct link generation/navigation behavior when tenant is in the first path segment, the referenced article shows a middleware approach using PathBase and a custom route contributor derived from RouteTenantResolveContributor.
  • Fix tenant context once a user enters via tenant-specific endpoint

    • The “fixed tenant” behavior is effectively achieved by only resolving tenant from the route (and not from headers/cookies/querystring), i.e. configure tenant resolve contributors to only use your preferred resolver. The route-based approach ensures subsequent requests under that base path keep resolving the same tenant.
  • Mapping tenants to different external authentication providers / enabling-disabling per tenant

    • No verified source available for built-in “tenant → provider mapping” that automatically enables/disables external providers per tenant inside the standard Account/OpenIddict UI out of the box.
    • Practically, to achieve “Tenant1 uses Entra+MyID, Tenant2 uses Challenge, Tenant3 uses Facebook+Local”، you typically need to customize the Account module login UI/flow and decide which schemes to show/challenge based on ICurrentTenant (tenant resolved before hitting /Account/Login via {__tenant} route).
  • Different OpenID Connect configurations per tenant (ClientId/Authority/Secret)

    • No verified source available for an official ABP sample implementing per-tenant external provider options (authority/client id/secret) while still using standard ABP Account + OpenIddict as-is.
    • The generally aligned approach in ABP apps is:
      1. Store per-tenant provider settings (e.g., in your own table or ABP Setting Management per-tenant).
      2. At runtime, when the tenant is resolved, configure/challenge the correct external scheme for that tenant (or implement dynamic options resolution).
      3. Customize the login page to only present the allowed providers for the current tenant.
  • Example / sample

    • I couldn’t find a verified official ABP sample that demonstrates “tenant-specific external authentication provider selection + per-tenant OIDC options” for AuthServer using standard Account/OpenIddict modules without customization.
    • The closest verified, relevant implementation guidance for tenant resolution from route is the community article below.

Links (validated):

  • https://abp.io/community/articles/ah7oru97
  • https://docs.abp.io/en/abp/latest/Multi-Tenancy
  • https://abp.io/docs/latest/framework/architecture/multi-tenancy

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.

  • That banner is coming from Blazorise, not from ABP itself. Blazorise is a third‑party UI component library and it shows that message when it decides your app is running without a valid Blazorise ProductToken (or when the token can’t be read/validated in the running UI).
  • In ABP’s Blazor templates that use Blazorise, you are expected to configure options.ProductToken in the Blazorise registration. If you don’t, Blazorise may display a “license expired / free version” footer/banner.

What you should do in an ABP Blazor solution

  1. Generate / obtain the Blazorise Product Token from Blazorise:

    • Go to the Blazorise license page and generate the token:
      https://blazorise.com/account/user/manage/license
  2. Configure it in both places when you use a server + WASM (or Blazor WebApp with interactive/WASM) style solution:

    • YourApp.Blazor → *BlazorModule.cs → ConfigureBlazorise()
    • YourApp.Blazor.Client → *BlazorClientModule.cs → ConfigureBlazorise()

    If you only put it into a server-side secrets file, the WASM/client side may not see it and the banner can appear after navigation (server prerender looks OK, then client becomes interactive and the footer/banner appears). ABP support confirmed this exact symptom and fix.

    Two working approaches:

    • Hardcode the token in the Client module (simplest).
    • Or put it into the WASM wwwroot/appsettings.json so the client can load it.

What happens if your ABP license expires?

  • This question is fundamentally about licensing terms (ABP + a 3rd-party vendor). I can’t give a definitive legal/contract answer here.
  • Technically, however, the behavior you see is controlled by Blazorise licensing checks. If a running app doesn’t have a valid Blazorise ProductToken (for whatever reason), Blazorise may show the banner. So your concern is valid from a technical dependency perspective: Blazorise can enforce its own licensing in the UI runtime.

Sources

  • ABP FAQ (ProductToken guidance): https://abp.io/faq#how-to-get-blazorise-license-key
  • ABP support (server vs WASM token visibility and the “appears after navigation” symptom/fix): https://abp.io/support/questions/10664
  • ABP support (ProductToken steps): https://abp.io/support/questions/9891
  • Blazorise token management page: https://blazorise.com/account/user/manage/license

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.

  • The root cause is that the downloaded Account.Pro Angular libraries are being compiled as separate Angular library projects, and with Angular’s newer builder + "moduleResolution": "bundler", TypeScript can fail to resolve workspace-external dependencies (like @abp/ng.core) consistently when you reference module source via tsconfig.paths (e.g., pointing to ../modules/.../projects/.../src/public-api.ts). This frequently manifests as TS2307 (module not found) or related Angular compiler/type-check issues in modular development scenarios.

  • The officially working approach (and the one that avoids this entire class of resolution problems) is to not compile these module projects through tsconfig.paths pointing to their source. Instead, use one of these two approaches:

    Option A (recommended): Consume the module UI as a built package (file:) instead of paths

    1. Build the Account.Pro Angular libraries (the projects under ../modules/Volo.Abp.Account.Pro/angular/projects/...) so they produce their dist outputs.
    2. In your main Angular app, reference them via package.json using file: (or a local tarball), rather than tsconfig.json paths into src/public-api.ts.
    3. Remove (or at least stop using) the paths entries that point into ../modules/.../projects/.../src/....

    This ensures there is one consistent dependency graph resolved from your main app’s node_modules.

    Option B: Use symlinks so module projects resolve dependencies from the main app’s node_modules

    If you must develop the module source “in place” inside the same repo, use a symlink strategy so the module library projects resolve the same physical @abp/* packages as the main app:

    1. Avoid “redirecting” ABP framework packages with paths mappings (mapping @abp/ng.core manually is a common way to end up with inconsistent resolution).
    2. Ensure the library projects under ../modules/.../angular/projects/... resolve dependencies from the main app’s angular/node_modules by symlinking (so they don’t behave like isolated workspaces with their own resolution roots).
  • About peer dependencies: Account.Pro Angular source projects expect the ABP Angular packages (like @abp/ng.core) to be available from the consuming app’s node_modules (same versions as your solution). When the module projects compile “isolated” and can’t see that node_modules consistently, you hit TS2307. Using Option A or B above fixes that by making dependency resolution consistent.

  • The "types": [] inside tsconfig.lib.json is not the core issue here; the problem is primarily the module resolution graph and the way the new builder handles paths + library compilation boundaries.

Sources:

  • https://abp.io/support/questions/10448
  • https://abp.io/docs/latest/framework/ui/angular/quick-start
  • https://abp.io/docs/10.0/framework/ui/angular/quick-start

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.

  • This error happens because your module’s Angular library project (e.g. modules/examplemodule/angular/...) ends up compiling against a different physical copy of Angular packages than the main app (App/angular/...). So TypeScript sees two different Routes types:

    • .../modules/examplemodule/angular/node_modules/@angular/router/...
    • .../angular/node_modules/@angular/router/... and they are incompatible even if versions look identical.
  • Definitive fix (recommended approach): ensure module UI projects use the main app’s node_modules via symlinks (single dependency graph).

    1. Keep the module source referenced via tsconfig paths (as ABP modular UI does), but do not allow the module project to have its own independent node_modules resolution.
    2. Use the ABP symlink scripts to link dependencies from App/angular/node_modules into each module’s angular/projects/... (or the module’s angular workspace) so everything resolves to one place.
    3. In practice, this means your symlink-config.ps1 should include at least these packages to be shared from the main app to the module libs:
      • @angular/*
      • rxjs
      • tslib
      • @abp/* / @volo/* (if used inside the module UI lib)

    This is exactly aligned with the behavior you observed: manually symlinking fixes it because it forces a single Angular dependency instance.

  • Stable alternative (also works, but slower for dev): build & consume the module UI as a package instead of paths

    • Build the module’s Angular library and reference it as a file: dependency from the main Angular app, avoiding tsconfig.paths pointing to library sources. This also prevents duplicate node_modules graphs.

Sources:

  • https://abp.io/community/articles/5z2ate6e
  • https://abp.io/docs/latest/framework/ui/angular/quick-start
  • https://abp.io/docs/latest/tutorials/modular-crm/part-02?UI=NG

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.

  • In ABP 8.2.x, Scriban is used through ABP Text Templating (Scriban) integration. ABP already enables Scriban’s “safe runtime” boundaries (restricted globals, restricted .NET member access via MemberFilter, no TemplateLoader by default, and execution limits like LoopLimit, RecursiveLimit, LimitToString, etc.). However, the CVE you described is specifically about array.insert_at bypassing those limits, so tightening LoopLimit/LimitToString alone is not a sufficient mitigation for that specific issue.

  • The practical mitigation in ABP without upgrading .NET / Scriban is therefore to ensure untrusted template authors cannot execute Scriban templates (i.e., don’t allow end users/tenants to edit arbitrary Scriban templates in production), and keep Scriban templates developer-owned and embedded/controlled (virtual file system, deployed with code). In other words: treat Scriban templates as trusted code/config, not user input.

  • If you must allow users to edit templates (e.g., Text Template Management scenarios), then within ABP 8.2.x there is no verified, ABP-provided switch documented to disable only array.insert_at or to hard-cap its index to prevent the allocation behavior in Scriban 5.9.0. In that case, the only fully effective remediation is upgrading Scriban to a fixed version (which you noted is blocked by your runtime constraint). So the ABP-side mitigation is to avoid exposing Scriban editing to untrusted parties until you can move to a fixed Scriban line.

  • Recommended ABP usage pattern (safe-by-design):

    1. Keep templates embedded (or otherwise shipped with the application) and not editable by end users.
    2. Pass a pre-built Dictionary<string, object> / ScriptObject as the model so the template surface area stays minimal and controlled (ABP recommends this pattern).
    3. Do not wire a custom TemplateLoader unless you absolutely need include behavior.

Sources (validated):

  • https://abp.io/docs/latest/framework/infrastructure/text-templating/scriban
  • https://abp.io/docs/10.4/framework/infrastructure/text-templating/scriban
  • https://abp.io/docs/latest/Text-Templating

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.

Showing 181 to 190 of 1374 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 October 21, 2026, 11:09
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.