Open Closed

Login Redirect Issue with Separate Blazor UI and AuthServer Projects #9585


User avatar
0
DuHK created

Hi, I have separated my solution into two independent projects:

Application UI (Blazor WebApp) for handling the frontend

Backend API & AuthServer for backend logic and authentication

Both projects run successfully. When I attempt to log in from the Application UI, it redirects me correctly to the AuthServer for authentication. However, after completing the login process, it redirects back to the UI but the user is still not logged in.

It seems like the login state is not preserved or there might be a misconfiguration in the redirection or cookie/token handling.

Can someone help me identify what might be missing or misconfigured in this scenario?

Thanks in advance!


10 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    • When using a separated AuthServer and Blazor UI in ABP, the most common cause for the login state not being preserved after redirection is a misconfiguration in the OpenIddict certificate, client settings, or cookie/token handling between the two applications.

    • Based on verified ABP support cases, here are the key points to check and resolve:

    1. Ensure the OpenIddict signing certificate (e.g., openiddict.pfx) and its passphrase are identical and correctly configured in both the AuthServer and the Backend API. A mismatch or missing certificate will prevent token validation, causing the UI to not recognize the login state.

    2. Double-check the client configuration in your AuthServer. The redirect_uri and post_logout_redirect_uri for your Blazor WebApp must exactly match the URLs used by your UI application.

    3. If you cloned or deployed the solution, make sure the openiddict.pfx file is present in both projects and not ignored by source control or missing on the server.

    4. If you see errors like SecurityTokenSignatureKeyNotFoundException or IDX10503 in logs, it indicates a certificate/key mismatch.

    5. For local development, ensure both applications use the same domain or set up proper CORS and SameSite cookie policies.

    6. If you are using HTTPS, ensure your certificates are trusted and valid for both domains.

    Example fix (from verified ABP support):

    • Sync the CertificatePassPhrase in both AuthServer and Backend API.
    • Generate a new openiddict.pfx and copy it to both projects.
    • Restart both applications.

    Sources (validated):

    • https://abp.io/support/questions/9274
    • https://abp.io/support/questions/899
    • https://abp.io/docs/latest/framework/ui/blazor/authentication

    This approach is confirmed by ABP support and documentation for separated AuthServer scenarios.


    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.

  • User Avatar
    0
    DuHK created

    I checked all of them and it still not login, here is configuration for backend:

    namespace HQSOFT.Xspire.Backend;

    [DependsOn( typeof(BackendHttpApiModule), typeof(AbpStudioClientAspNetCoreModule), typeof(AbpAspNetCoreMvcUiLeptonThemeModule), typeof(AbpAutofacModule), typeof(AbpAspNetCoreMultiTenancyModule), typeof(BackendApplicationModule), typeof(BackendEntityFrameworkCoreModule), typeof(AbpAccountPublicWebImpersonationModule), typeof(AbpAccountPublicWebOpenIddictModule), typeof(AbpSwashbuckleModule), typeof(AbpAspNetCoreSerilogModule) )] public class BackendHttpApiHostModule : AbpModule { public override void PreConfigureServices(ServiceConfigurationContext context) { var hostingEnvironment = context.Services.GetHostingEnvironment(); var configuration = context.Services.GetConfiguration();

        PreConfigure<OpenIddictBuilder>(builder =>
        {
            builder.AddValidation(options =>
            {
                options.AddAudiences("AuthServer");
                options.UseLocalServer();
                options.UseAspNetCore();
            });
        });
    
        if (!hostingEnvironment.IsDevelopment())
        {
            PreConfigure<AbpOpenIddictAspNetCoreOptions>(options =>
            {
                options.AddDevelopmentEncryptionAndSigningCertificate = false;
            });
    
            PreConfigure<OpenIddictServerBuilder>(serverBuilder =>
            {
                serverBuilder.AddProductionEncryptionAndSigningCertificate("openiddict.pfx", configuration["AuthServer:CertificatePassPhrase"]!);
                serverBuilder.SetIssuer(new Uri(configuration["AuthServer:Authority"]!));
            });
        }
    }
    
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        var configuration = context.Services.GetConfiguration();
        var hostingEnvironment = context.Services.GetHostingEnvironment();
    
        if (!configuration.GetValue<bool>("App:DisablePII"))
        {
            Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
            Microsoft.IdentityModel.Logging.IdentityModelEventSource.LogCompleteSecurityArtifact = true;
        }
    
        if (!configuration.GetValue<bool>("AuthServer:RequireHttpsMetadata"))
        {
            Configure<OpenIddictServerAspNetCoreOptions>(options =>
            {
                options.DisableTransportSecurityRequirement = true;
            });
            
            Configure<ForwardedHeadersOptions>(options =>
            {
                options.ForwardedHeaders = ForwardedHeaders.XForwardedProto;
            });
        }
    
        ConfigureAuthentication(context, configuration);
        ConfigureUrls(configuration);
        //ConfigureBundles();
        ConfigureConventionalControllers();
        ConfigureExternalProviders(context);
        ConfigureImpersonation(context, configuration);
        ConfigureHealthChecks(context);
        ConfigureSwagger(context, configuration);
        ConfigureVirtualFileSystem(context);
        ConfigureCors(context, configuration);
        //ConfigureTheme();
    }
    
    /*private void ConfigureTheme()
    {
        Configure<LeptonXThemeOptions>(options =>
        {
            options.DefaultStyle = LeptonXStyleNames.System;
        });
    }*/
    
    private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
    {
        context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddAbpJwtBearer(options =>
            {
                options.Authority = configuration["AuthServer:Authority"];
                options.RequireHttpsMetadata = configuration.GetValue<bool>("AuthServer:RequireHttpsMetadata");
                options.Audience = "AuthServer";
            });
    
        context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
        {
            options.IsDynamicClaimsEnabled = true;
        });
    }
    private void ConfigureUrls(IConfiguration configuration)
    {
        Configure<AppUrlOptions>(options =>
        {
            options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"];
            options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"]?.Split(',') ?? Array.Empty<string>());
        });
    }
    

    /* private void ConfigureBundles() { Configure<AbpBundlingOptions>(options => { options.StyleBundles.Configure( LeptonXThemeBundles.Styles.Global, bundle => { bundle.AddFiles("/global-styles.css"); } );

            options.ScriptBundles.Configure(
                LeptonXThemeBundles.Scripts.Global,
                bundle =>
                {
                    bundle.AddFiles("/global-scripts.js");
                }
            );
        });
    }*/
    
    
    private void ConfigureVirtualFileSystem(ServiceConfigurationContext context)
    {
        var hostingEnvironment = context.Services.GetHostingEnvironment();
    
        if (hostingEnvironment.IsDevelopment())
        {
            Configure&lt;AbpVirtualFileSystemOptions&gt;(options =>
            {
                options.FileSets.ReplaceEmbeddedByPhysical&lt;BackendDomainSharedModule&gt;(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}HQSOFT.Xspire.Backend.Domain.Shared"));
                options.FileSets.ReplaceEmbeddedByPhysical&lt;BackendDomainModule&gt;(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}HQSOFT.Xspire.Backend.Domain"));
                options.FileSets.ReplaceEmbeddedByPhysical&lt;BackendApplicationContractsModule&gt;(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}HQSOFT.Xspire.Backend.Application.Contracts"));
                options.FileSets.ReplaceEmbeddedByPhysical&lt;BackendApplicationModule&gt;(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}HQSOFT.Xspire.Backend.Application"));
            });
        }
    }
    
    private void ConfigureConventionalControllers()
    {
        Configure&lt;AbpAspNetCoreMvcOptions&gt;(options =>
        {
            options.ConventionalControllers.Create(typeof(BackendApplicationModule).Assembly);
        });
    }
    
    private static void ConfigureSwagger(ServiceConfigurationContext context, IConfiguration configuration)
    {
        context.Services.AddAbpSwaggerGenWithOidc(
            configuration["AuthServer:Authority"]!,
            ["AuthServer"],
            [AbpSwaggerOidcFlows.AuthorizationCode],
            null,
            options =>
            {
                options.SwaggerDoc("v1", new OpenApiInfo { Title = "AuthServer API", Version = "v1" });
                options.DocInclusionPredicate((docName, description) => true);
                options.CustomSchemaIds(type => type.FullName);
            });
    }
    
    private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration)
    {
        context.Services.AddCors(options =>
        {
            options.AddDefaultPolicy(builder =>
            {
                builder
                    .WithOrigins(
                        configuration["App:CorsOrigins"]?
                            .Split(",", StringSplitOptions.RemoveEmptyEntries)
                            .Select(o => o.Trim().RemovePostFix("/"))
                            .ToArray() ?? Array.Empty&lt;string&gt;()
                    )
                    .WithAbpExposedHeaders()
                    .SetIsOriginAllowedToAllowWildcardSubdomains()
                    .AllowAnyHeader()
                    .AllowAnyMethod()
                    .AllowCredentials();
            });
        });
    }
    
    private void ConfigureExternalProviders(ServiceConfigurationContext context)
    {
        context.Services.AddAuthentication()
            .AddGoogle(GoogleDefaults.AuthenticationScheme, options =>
            {
                options.ClaimActions.MapJsonKey(AbpClaimTypes.Picture, "picture");
            })
            .WithDynamicOptions&lt;GoogleOptions, GoogleHandler&gt;(
                GoogleDefaults.AuthenticationScheme,
                options =>
                {
                    options.WithProperty(x => x.ClientId);
                    options.WithProperty(x => x.ClientSecret, isSecret: true);
                }
            )
            .AddMicrosoftAccount(MicrosoftAccountDefaults.AuthenticationScheme, options =>
            {
                //Personal Microsoft accounts as an example.
                options.AuthorizationEndpoint = "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize";
                options.TokenEndpoint = "https://login.microsoftonline.com/consumers/oauth2/v2.0/token";
    
                options.ClaimActions.MapCustomJson("picture", _ => "https://graph.microsoft.com/v1.0/me/photo/$value");
                options.SaveTokens = true;
            })
            .WithDynamicOptions&lt;MicrosoftAccountOptions, MicrosoftAccountHandler&gt;(
                MicrosoftAccountDefaults.AuthenticationScheme,
                options =>
                {
                    options.WithProperty(x => x.ClientId);
                    options.WithProperty(x => x.ClientSecret, isSecret: true);
                }
            )
            .AddTwitter(TwitterDefaults.AuthenticationScheme, options =>
            {
                options.ClaimActions.MapJsonKey(AbpClaimTypes.Picture, "profile_image_url_https");
                options.RetrieveUserDetails = true;
            })
            .WithDynamicOptions&lt;TwitterOptions, TwitterHandler&gt;(
                TwitterDefaults.AuthenticationScheme,
                options =>
                {
                    options.WithProperty(x => x.ConsumerKey);
                    options.WithProperty(x => x.ConsumerSecret, isSecret: true);
                }
            );
    }
    
    private void ConfigureImpersonation(ServiceConfigurationContext context, IConfiguration configuration)
    {
        context.Services.Configure&lt;AbpAccountOptions&gt;(options =>
        {
            options.TenantAdminUserName = "admin";
            options.ImpersonationTenantPermission = SaasHostPermissions.Tenants.Impersonation;
            options.ImpersonationUserPermission = IdentityPermissions.Users.Impersonation;
        });
    }
    
    private void ConfigureHealthChecks(ServiceConfigurationContext context)
    {
        context.Services.AddBackendHealthChecks();
    }
    
    public override void OnApplicationInitialization(ApplicationInitializationContext context)
    {
        var app = context.GetApplicationBuilder();
        var env = context.GetEnvironment();
    
        app.UseForwardedHeaders();
    
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
    
        app.UseAbpRequestLocalization();
    
        if (!env.IsDevelopment())
        {
            app.UseErrorPage();
        }
    
        app.UseRouting();
        app.MapAbpStaticAssets();
        app.UseAbpStudioLink();
        app.UseAbpSecurityHeaders();
        app.UseCors();
        app.UseAuthentication();
        app.UseAbpOpenIddictValidation();
    
        if (MultiTenancyConsts.IsEnabled)
        {
            app.UseMultiTenancy();
        }
    
        app.UseUnitOfWork();
        app.UseDynamicClaims();
        app.UseAuthorization();
    
        app.UseSwagger();
        app.UseAbpSwaggerUI(options =>
        {
            options.SwaggerEndpoint("/swagger/v1/swagger.json", "AuthServer API");
    
            var configuration = context.ServiceProvider.GetRequiredService&lt;IConfiguration&gt;();
            options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
        });
        app.UseAuditing();
        app.UseAbpSerilogEnrichers();
        app.UseConfiguredEndpoints();
    }
    

    }

  • User Avatar
    0
    DuHK created

    and here is configuration file for UI Application:

    namespace HQSOFT.Xspire.Application.Blazor;

    [DependsOn( typeof(AbpCachingStackExchangeRedisModule), typeof(AbpDistributedLockingModule), typeof(AbpAutofacModule), typeof(AbpAccountPublicBlazorWebAssemblyBundlingModule), typeof(AbpAccountPublicWebImpersonationModule), typeof(AbpAccountAdminBlazorServerModule), typeof(AbpAccountPublicBlazorServerModule), typeof(AbpIdentityProBlazorServerModule), typeof(TextTemplateManagementBlazorServerModule), typeof(AbpAuditLoggingBlazorServerModule), typeof(AbpAuditLoggingBlazorWebAssemblyBundlingModule), typeof(AbpGdprBlazorServerModule), typeof(AbpOpenIddictProBlazorServerModule), typeof(LanguageManagementBlazorServerModule), typeof(FileManagementBlazorServerModule), typeof(FileManagementBlazorWebAssemblyBundlingModule), typeof(SaasHostBlazorServerModule), typeof(SaasHostBlazorWebAssemblyBundlingModule), typeof(LeptonXThemeManagementBlazorServerModule), typeof(AbpAspNetCoreComponentsServerLeptonXThemeModule), typeof(AbpAspNetCoreComponentsWebAssemblyLeptonXThemeBundlingModule), typeof(AbpAspNetCoreMvcUiLeptonXThemeModule), typeof(AbpSwashbuckleModule), typeof(AbpAspNetCoreSerilogModule), typeof(AbpAspNetCoreMvcClientModule), typeof(AbpAspNetCoreAuthenticationOpenIdConnectModule), typeof(AbpHttpClientWebModule), typeof(BackendHttpApiClientModule) )] public class ApplicationBlazorModule : AbpModule { public override void PreConfigureServices(ServiceConfigurationContext context) { context.Services.PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options => { options.AddAssemblyResource( typeof(BackendResource), typeof(BackendDomainSharedModule).Assembly, typeof(BackendApplicationContractsModule).Assembly, typeof(ApplicationBlazorModule).Assembly ); });

        PreConfigure&lt;AbpAspNetCoreComponentsWebOptions&gt;(options =>
        {
            options.IsBlazorWebApp = true;
        });
    }
    
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        var hostingEnvironment = context.Services.GetHostingEnvironment();
        var configuration = context.Services.GetConfiguration();
    
        if (!configuration.GetValue&lt;bool&gt;("App:DisablePII"))
        {
            Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
            Microsoft.IdentityModel.Logging.IdentityModelEventSource.LogCompleteSecurityArtifact = true;
        }
    
        // Add services to the container.
        context.Services.AddRazorComponents()
            .AddInteractiveServerComponents()
            .AddInteractiveWebAssemblyComponents();
        // Add DevExpress
        context.Services.AddDevExpressBlazor();
    
        ConfigureUrls(configuration);
        ConfigureBundles();
        ConfigureAuthentication(context, configuration);
        ConfigureImpersonation(context, configuration);
        ConfigureAutoMapper();
        //ConfigureVirtualFileSystem(hostingEnvironment);
        ConfigureSwaggerServices(context.Services);
        ConfigureCache(configuration);
        ConfigureDataProtection(context, configuration, hostingEnvironment);
        ConfigureDistributedLocking(context, configuration);
        ConfigureBlazorise(context);
        ConfigureRouter();
        ConfigureMenu(configuration);
        ConfigureCookieConsent(context);
        ConfigureTheme();
    }
    
    private void ConfigureCookieConsent(ServiceConfigurationContext context)
    {
        context.Services.AddAbpCookieConsent(options =>
        {
            options.IsEnabled = true;
            options.CookiePolicyUrl = "/CookiePolicy";
            options.PrivacyPolicyUrl = "/PrivacyPolicy";
        });
    }
    
    private void ConfigureTheme()
    {
        Configure&lt;LeptonXThemeOptions&gt;(options =>
        {
            options.DefaultStyle = LeptonXStyleNames.System;
        });
    
        Configure&lt;LeptonXThemeBlazorOptions&gt;(options =>
        {
            options.Layout = LeptonXBlazorLayouts.SideMenu;
        });
    }
    
    private void ConfigureUrls(IConfiguration configuration)
    {
        Configure&lt;AppUrlOptions&gt;(options =>
        {
            options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"];
        });
    
        Configure&lt;AbpAccountLinkUserOptions&gt;(options =>
        {
            options.LoginUrl = configuration["AuthServer:Authority"];
        });
    }
    
    private void ConfigureBundles()
    {
        Configure&lt;AbpBundlingOptions&gt;(options =>
        {
            // Blazor Web App
            options.Parameters.InteractiveAuto = true;
    
            // MVC UI
            options.StyleBundles.Configure(
                LeptonXThemeBundles.Styles.Global,
                bundle =>
                {
                    bundle.AddFiles("/global-styles.css");
                }
            );
    
            options.ScriptBundles.Configure(
                LeptonXThemeBundles.Scripts.Global,
                bundle =>
                {
                    bundle.AddFiles("/global-scripts.js");
                }
            );
    
            // Blazor UI
            options.StyleBundles.Configure(
                BlazorLeptonXThemeBundles.Styles.Global,
                bundle =>
                {
                    bundle.AddFiles("/global-styles.css");
                }
            );
        });
    
        Configure&lt;AbpBundlingOptions&gt;(options =>
        {
            var globalStyles = options.StyleBundles.Get(BlazorWebAssemblyStandardBundles.Styles.Global);
            globalStyles.AddContributors(typeof(ApplicationStyleBundleContributor));
    
            var globalScripts = options.ScriptBundles.Get(BlazorWebAssemblyStandardBundles.Scripts.Global);
            globalScripts.AddContributors(typeof(ApplicationScriptBundleContributor));
    
            options.Parameters["LeptonXTheme.Layout"] = "side-menu"; // side-menu or top-menu
        });
    }
    
    private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
    {
        context.Services.AddAuthentication(options =>
            {
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";
            })
            .AddCookie("Cookies", options =>
            {
                options.ExpireTimeSpan = TimeSpan.FromDays(365);
                options.IntrospectAccessToken();
            })
            .AddAbpOpenIdConnect("oidc", options =>
            {
                options.Authority = configuration["AuthServer:Authority"];
                options.RequireHttpsMetadata = configuration.GetValue&lt;bool&gt;("AuthServer:RequireHttpsMetadata");;
                options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
    
                options.ClientId = configuration["AuthServer:ClientId"];
                options.ClientSecret = configuration["AuthServer:ClientSecret"];
    
                options.SaveTokens = true;
                options.GetClaimsFromUserInfoEndpoint = true;
    
                options.Scope.Add("roles");
                options.Scope.Add("email");
                options.Scope.Add("phone");
                options.Scope.Add("AuthServer");
            });
    
            if (configuration.GetValue&lt;bool&gt;("AuthServer:IsOnK8s"))
            {
                context.Services.Configure&lt;OpenIdConnectOptions&gt;("oidc", options =>
                {
                    options.TokenValidationParameters.ValidIssuers = new[]
                    {
                        configuration["AuthServer:MetaAddress"]!.EnsureEndsWith('/'),
                        configuration["AuthServer:Authority"]!.EnsureEndsWith('/')
                    };
    
                    options.MetadataAddress = configuration["AuthServer:MetaAddress"]!.EnsureEndsWith('/') +
                                            ".well-known/openid-configuration";
    
                    var previousOnRedirectToIdentityProvider = options.Events.OnRedirectToIdentityProvider;
                    options.Events.OnRedirectToIdentityProvider = async ctx =>
                    {
                        // Intercept the redirection so the browser navigates to the right URL in your host
                        ctx.ProtocolMessage.IssuerAddress = configuration["AuthServer:Authority"]!.EnsureEndsWith('/') + "connect/authorize";
    
                        if (previousOnRedirectToIdentityProvider != null)
                        {
                            await previousOnRedirectToIdentityProvider(ctx);
                        }
                    };
                    var previousOnRedirectToIdentityProviderForSignOut = options.Events.OnRedirectToIdentityProviderForSignOut;
                    options.Events.OnRedirectToIdentityProviderForSignOut = async ctx =>
                    {
                        // Intercept the redirection for signout so the browser navigates to the right URL in your host
                        ctx.ProtocolMessage.IssuerAddress = configuration["AuthServer:Authority"]!.EnsureEndsWith('/') + "connect/logout";
    
                        if (previousOnRedirectToIdentityProviderForSignOut != null)
                        {
                            await previousOnRedirectToIdentityProviderForSignOut(ctx);
                        }
                    };
                });
    
            }
    
        context.Services.Configure&lt;AbpClaimsPrincipalFactoryOptions&gt;(options =>
        {
            options.IsDynamicClaimsEnabled = true;
    
        });
    }
    
    private void ConfigureImpersonation(ServiceConfigurationContext context, IConfiguration configuration)
    {
        context.Services.Configure&lt;SaasHostBlazorOptions&gt;(options =>
        {
            options.EnableTenantImpersonation = true;
        });
        context.Services.Configure&lt;AbpIdentityProBlazorOptions&gt;(options =>
        {
            options.EnableUserImpersonation = true;
        });
    }
    

    /* private void ConfigureVirtualFileSystem(IWebHostEnvironment hostingEnvironment) { if (hostingEnvironment.IsDevelopment()) { Configure<AbpVirtualFileSystemOptions>(options => { options.FileSets.ReplaceEmbeddedByPhysical<ApplicationDomainSharedModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}HQSOFT.Xspire.Application.Domain.Shared")); options.FileSets.ReplaceEmbeddedByPhysical<ApplicationApplicationContractsModule>(Path.Combine(hostingEnvironment.ContentRootPath, $"..{Path.DirectorySeparatorChar}HQSOFT.Xspire.Application.Application.Contracts")); options.FileSets.ReplaceEmbeddedByPhysical<ApplicationBlazorModule>(hostingEnvironment.ContentRootPath); }); } }*/

    private void ConfigureSwaggerServices(IServiceCollection services)
    {
        services.AddAbpSwaggerGen(
            options =>
            {
                options.SwaggerDoc("v1", new OpenApiInfo { Title = "AuthServer API", Version = "v1" });
                options.DocInclusionPredicate((docName, description) => true);
                options.CustomSchemaIds(type => type.FullName);
            }
        );
    }
    
    private void ConfigureCache(IConfiguration configuration)
    {
        Configure&lt;AbpDistributedCacheOptions&gt;(options =>
        {
            options.KeyPrefix = "AuthServer:";
        });
    }
    
    private void ConfigureDataProtection(
        ServiceConfigurationContext context,
        IConfiguration configuration,
        IWebHostEnvironment hostingEnvironment)
    {
        var dataProtectionBuilder = context.Services.AddDataProtection().SetApplicationName("AuthServer");
        if (!hostingEnvironment.IsDevelopment())
        {
            var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!);
            dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "Application-Protection-Keys");
        }
    }
    
    private void ConfigureDistributedLocking(
        ServiceConfigurationContext context,
        IConfiguration configuration)
    {
        context.Services.AddSingleton&lt;IDistributedLockProvider&gt;(sp =>
        {
            var connection = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]!);
            return new RedisDistributedSynchronizationProvider(connection.GetDatabase());
        });
    }
    
    private void ConfigureBlazorise(ServiceConfigurationContext context)
    {
        context.Services
            .AddBootstrap5Providers()
            .AddFontAwesomeIcons();
    }
    
    private void ConfigureMenu(IConfiguration configuration)
    {
        Configure&lt;AbpNavigationOptions&gt;(options =>
        {
            options.MenuContributors.Add(new ApplicationMenuContributor(configuration));
        });
    }
    
    private void ConfigureRouter()
    {
        Configure&lt;AbpRouterOptions&gt;(options =>
        {
            options.AppAssembly = typeof(ApplicationBlazorModule).Assembly;
            options.AdditionalAssemblies.Add(typeof(ApplicationBlazorClientModule).Assembly);
        });
    }
    
    private void ConfigureAutoMapper()
    {
        Configure&lt;AbpAutoMapperOptions&gt;(options =>
        {
            options.AddMaps&lt;ApplicationBlazorModule&gt;();
        });
    }
    
    public override void OnApplicationInitialization(ApplicationInitializationContext context)
    {
        var env = context.GetEnvironment();
        var app = context.GetApplicationBuilder();
    
        app.Use(async (ctx, next) =>
        {
            /* Converting to https to be able to include https URLs in `/.well-known/openid-configuration` endpoint.
             * This should only be done if the request is coming outside of the cluster.  */
            if (ctx.Request.Headers.ContainsKey("from-ingress"))
            {
                ctx.Request.Scheme = "https";
            }
    
            await next();
        });     
        
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
    
        app.UseAbpRequestLocalization();
    
        if (!env.IsDevelopment())
        {
            app.UseErrorPage();
            app.UseHsts();
        }
    
        app.UseCorrelationId();
        app.UseRouting();
        var configuration = context.GetConfiguration();
        if (Convert.ToBoolean(configuration["AuthServer:IsOnK8s"]))
        {
            app.Use(async (context, next) =>
            {
                if (context.Request.Path.Value != null &&
                    context.Request.Path.Value.StartsWith("/appsettings", StringComparison.OrdinalIgnoreCase) &&
                    context.Request.Path.Value.EndsWith(".json", StringComparison.OrdinalIgnoreCase))
                {
                    // Set endpoint to null so the static files middleware will handle the request.
                    context.SetEndpoint(null);
                }
                await next(context);
            });
    
            app.UseStaticFilesForPatterns("appsettings*.json");
        }
        
        app.MapAbpStaticAssets();
        app.UseAbpSecurityHeaders();
        app.UseAuthentication();
    
        if (MultiTenancyConsts.IsEnabled)
        {
            app.UseMultiTenancy();
        }
    
        app.UseDynamicClaims();
        app.UseAntiforgery();
        app.UseAuthorization();
        app.UseSwagger();
        app.UseAbpSwaggerUI(options =>
        {
            options.SwaggerEndpoint("/swagger/v1/swagger.json", "Application API");
        });
        app.UseAbpSerilogEnrichers();
        app.UseConfiguredEndpoints(builder =>
        {
            builder.MapRazorComponents&lt;App&gt;()
                .AddInteractiveServerRenderMode()
                .AddInteractiveWebAssemblyRenderMode()
                .AddAdditionalAssemblies(builder.ServiceProvider.GetRequiredService&lt;IOptions&lt;AbpRouterOptions&gt;>().Value.AdditionalAssemblies.ToArray());
        });
    }
    

    }

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Can you share a template project that reproduces the issue?

    liming.ma@volosoft.com

    Thanks.

  • User Avatar
    0
    DuHK created

    [maliming] said: hi

    Can you share a template project that reproduces the issue?

    liming.ma@volosoft.com

    Thanks.

    I have sent the sample project to your email.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    I get an error while building your project.

    error NU1101: Unable to find package HQSOFT.Xspire.Backend.HttpApi.Client. 
    
    

    Can you try to update the ConfigureAuthentication method as below?

    private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
    {
    context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
        context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
        {
            options.IsDynamicClaimsEnabled = true;
        });
    }
    

    Thanks.

  • User Avatar
    0
    DuHK created

    [maliming] said: hi

    I get an error while building your project.

    error NU1101: Unable to find package HQSOFT.Xspire.Backend.HttpApi.Client.  
     
    

    Can you try to update the ConfigureAuthentication method as below?

    private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration) 
    { 
    context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme); 
        context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options => 
        { 
            options.IsDynamicClaimsEnabled = true; 
        }); 
    } 
    

    Thanks.

    Hi I have set up the build process to generate backend packages. Please build the Backend to produce those packages for installation into the application. Configure the path in the package sources and try building the application again

    I tried the method you suggested, but it still didn't work.

    Thanks

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    1, Add AbpHttpClientIdentityModelWebModule to your ApplicationBlazorModule

    2, Add AbpCachingStackExchangeRedisModule to your BackendHttpApiHostModule

    3, Update BackendHttpApiHostModule's ConfigureAuthentication as below:

    private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
    {
        Configure<AbpDistributedCacheOptions>(options =>
        {
            options.KeyPrefix = "AuthServer:";
        });
        context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
        context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
        {
            options.IsDynamicClaimsEnabled = true;
        });
    }
    

    Your Blazor and API need to enable the Redis and use the same KeyPrefix.

    Thanks.

  • User Avatar
    0
    DuHK created

    [maliming] said: hi

    1, Add AbpHttpClientIdentityModelWebModule to your ApplicationBlazorModule

    2, Add AbpCachingStackExchangeRedisModule to your BackendHttpApiHostModule

    3, Update BackendHttpApiHostModule's ConfigureAuthentication as below:

    private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration) 
    { 
        Configure<AbpDistributedCacheOptions>(options => 
        { 
            options.KeyPrefix = "AuthServer:"; 
        }); 
        context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme); 
        context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options => 
        { 
            options.IsDynamicClaimsEnabled = true; 
        }); 
    } 
    

    Your Blazor and API need to enable the Redis and use the same KeyPrefix.

    Thanks.

    hi I have solved the problem, thank you very much!

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Great

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.0.0-preview. Updated on September 18, 2025, 07:10