Cause
Fix
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAbpRequestLocalization();
app.UseStaticFiles(); // 1: physical wwwroot
app.UseAbpStaticFiles(); // 2: embedded static files from ABP modules
app.UseRouting();
app.UseAuthentication();
app.UseJwtTokenMiddleware();
app.UseAbpClaimsMap();
app.UseAuthorization();
app.UseAuditing();
app.UseConfiguredEndpoints();
}
public class DocsThemeGlobalContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
var style = context.Files;
// styles
style.AddIfNotContains("/libs/@fortawesome/fontawesome-free/css/all.min.css");
var script = context.Files;
// scripts
script.AddIfNotContains("/libs/jquery/jquery.js");
script.AddIfNotContains("/libs/select2/js/select2.full.min.js");
script.AddIfNotContains("/libs/moment/moment.js");
// add any i18n files you actually use:
// script.AddIfNotContains("/libs/select2/js/i18n/en.js");
}
}
That’s Font Awesome not loading. Once /libs/@fortawesome/fontawesome-free/webfonts/... are served correctly (steps 1–3), the icons will render.
Quick checklist for your screenshots
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.
A) Recommended: Use Releases/Tags as versions
B) If you must use Branches as versions
Additional checks
Quick apply to your screenshots
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.
Notes:
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.
Yes. ABP supports showing an OTP step after a successful username/password login (Two-Factor Authentication). Users can use Email, SMS, or an Authenticator app. You can allow the user to choose Email or SMS on the OTP screen, or you can restrict to one provider.
Enable 2FA and providers:
How the built-in flow works:
Let the user choose Email or SMS:
public class MyAccountAppService : AccountAppService
{
public override async Task<ListResultDto<NameValue>> GetTwoFactorProvidersAsync(GetTwoFactorProvidersInput input)
{
var result = await base.GetTwoFactorProvidersAsync(input);
// Keep only Email and SMS
result.Items = result.Items.Where(p => p.Name == "Email" || p.Name == "SMS").ToList();
return result;
}
}
Register your derived service in your module to replace the default IAccountAppService.
If you want to force a single provider (e.g., SMS only) and remove the dropdown:
Notes and prerequisites:
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.
Do this checklist and fix:
Generate a proper OpenIddict certificate for production (not the site TLS cert)
Configure ABP OpenIddict to use the PFX in production
public override void PreConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
var configuration = context.Services.GetConfiguration();
if (!hostingEnvironment.IsDevelopment())
{
PreConfigure<AbpOpenIddictAspNetCoreOptions>(options =>
{
options.AddDevelopmentEncryptionAndSigningCertificate = false;
});
PreConfigure<OpenIddictServerBuilder>(serverBuilder =>
{
// If your pfx is in content root
serverBuilder.AddProductionEncryptionAndSigningCertificate(
"openiddict.pfx",
"00000000-0000-0000-0000-000000000000"
);
// Set the public HTTPS issuer
serverBuilder.SetIssuer(new Uri(configuration["AuthServer:Authority"]!));
});
}
}
PreConfigure<OpenIddictServerBuilder>(serverBuilder =>
{
var flags = X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.EphemeralKeySet;
serverBuilder.AddProductionEncryptionAndSigningCertificate("openiddict.pfx", "00000000-0000-0000-0000-000000000000", flags);
});
Ensure the file is actually present on the server
Keep Authority and metadata HTTPS-only
"AuthServer": {
"Authority": "https://your-authserver-host",
"RequireHttpsMetadata": true,
"CertificatePassPhrase": "00000000-0000-0000-0000-000000000000"
}
app.Use(async (ctx, next) =>
{
ctx.Request.Scheme = "https";
await next();
});
If you temporarily set RequireHttpsMetadata = false, discovery will emit http URLs and SPAs will reject them; keep it true and fix scheme/forwarding instead.
About the “key rollover” message
IIS-specific tips
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.
What to change
Example const routes: Routes = [ { path: 'identity', loadChildren: () => import('@volo/abp.ng.identity').then(m => m.createRoutes()) }, { path: 'saas', loadChildren: () => import('@volo/abp.ng.saas').then(m => m.createRoutes()) }, { path: 'audit-logging', loadChildren: () => import('@volo/abp.ng.audit-logging').then(m => m.createRoutes()) }, { path: 'language-management', loadChildren: () => import('@volo/abp.ng.language-management').then(m => m.createRoutes()) }, { path: 'text-template-management', loadChildren: () => import('@volo/abp.ng.text-template-management').then(m => m.createRoutes()) }, { path: 'account', loadChildren: () => import('@volo/abp.ng.account').then(m => m.createRoutes()) }, ];
Notes
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 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.
Apply these steps:
Use createRoutes for SAAS routes (even in a module-based app) In your AppRoutingModule (or wherever you define feature routes), load the Saas routes using the package’s route factory. This ensures the Tenants standalone component receives its providers.
Example: import { RouterModule, Routes } from '@angular/router'; import { createRoutes as createSaasRoutes } from '@volo/abp.ng.saas';
const routes: Routes = [ { path: 'saas', loadChildren: () => import('@volo/abp.ng.saas').then(m => createSaasRoutes()), }, // ...other routes ];
@NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule], }) export class AppRoutingModule {}
Keep provideSaasConfig() in root providers You already have:
That’s fine. The critical part is that the route uses createSaasRoutes() so the Tenants standalone component runs with the correct Feature providers. If you currently lazy-load a module via SaasConfigModule.forRoot() alone or navigate to the component outside its created routes, the DI context misses feature tokens.
Do not declare or import TenantsComponent manually Don’t import or declare _TenantsComponent (or any SAAS component) directly in your own module. Always navigate through the SAAS routes returned by createSaasRoutes().
Version alignment Ensure all ABP/Commercial Angular packages are on the same exact version range as the ABP CLI template you’re targeting, and Angular is aligned. For ABP 9.3.6:
If you previously used forLazy() Replace any old lazy-load syntax like: loadChildren: () => import('@volo/abp.ng.saas').then(m => m.SaasModule.forLazy({...})) with the new: loadChildren: () => import('@volo/abp.ng.saas').then(m => m.createRoutes({...}))
Last-resort guard If you still see the InjectionToken undefined from a standalone component, it almost always means that page is rendered outside its feature route tree. Double-check that:
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.
What Volo.Abp.Cli is and how it’s used
Why it appears in your vulnerability scan after upgrading to 8.3.4
How to remove or mitigate the vulnerability finding
Important notes
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.
Check and fix the following:
app.UseRouting();
app.UseAuthentication();
app.UseMultiTenancy();
app.UseAuthorization();
Wrong order (multi-tenancy before authentication) leads to missing tenant context during DbContext creation and thus host DB usage.
using (_currentTenant.Change(tenantId))
{
// Resolve repositories/DbContexts here, after tenant has been set
var ctx = await repository.GetDbContextAsync();
// Now ctx.Database.GetConnectionString() should be the tenant’s connection string
}
Do not cache DbContext, DbContextOptions, or services that depend on tenant context across tenant boundaries.
Configure<AbpDbContextOptions>(options =>
{
options.UseSqlServer(); // no literal connection string here
});
If you pass a literal connection string in UseSqlServer, it will always use that (host) connection, bypassing the resolver.
[ConnectionStringName("Default")]
public class MyDbContext : AbpDbContext<MyDbContext> { ... }
Since your checks show ConnectionStringNameAttribute.GetConnStringName returns the correct name and the resolver returns the tenant string, this is likely fine.
[Dependency(ReplaceServices = true)]
public class EncryptedConnectionStringChecker : SqlServerConnectionStringChecker
{
private readonly IStringEncryptionService _enc;
public EncryptedConnectionStringChecker(IStringEncryptionService enc) => _enc = enc;
public override Task<AbpConnectionStringCheckResult> CheckAsync(string cs)
=> base.CheckAsync(_enc.Decrypt(cs));
}
Don’t read Database.GetConnectionString too early If you log dbContext.Database.GetConnectionString() before the tenant scope is active or before the provider initializes, you may see host/null. Inspect after resolving DbContext within the tenant scope.
Background workers and integration events For hosted services, background jobs, or event handlers (out of HTTP pipeline), wrap operations with _currentTenant.Change(tenantId) before resolving repositories/DbContexts.
Minimal checklist you can try now:
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.