Open Closed

Error after OpenIddict Migration #4588


User avatar
0

We're working on upgrading our solution though we needed to migrate from IdentityServer to OpenIddict first. We followed this guide: https://docs.abp.io/en/commercial/latest/migration-guides/openIddict-step-by-step and https://docs.abp.io/en/commercial/latest/migration-guides/openIddict-mvc#web-project-tiered-solution and after a bit of fiddling with the application URLs we're getting the following:

ComponentNotRegisteredException: The requested service 'Volo.Abp.Account.Public.Web.Pages.Account.LogoutModel' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.

  • ABP Framework version: v6.0
  • UI type: MVC
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): Tiered/yes
  • Exception message and stack trace:
Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable<Parameter> parameters)
Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.DefaultPageModelFactoryProvider+<>c__DisplayClass3_0.<CreateModelFactory>b__0(PageContext pageContext)
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.CreateInstance()
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeInnerFilterAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ExceptionContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeNextResourceFilter()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
Volo.Abp.AspNetCore.Serilog.AbpSerilogMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext()
Volo.Abp.AspNetCore.Auditing.AbpAuditingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
Volo.Abp.AspNetCore.Auditing.AbpAuditingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext()
Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
StackExchange.Profiling.MiniProfilerMiddleware.Invoke(HttpContext context) in MiniProfilerMiddleware.cs
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Volo.Abp.AspNetCore.MultiTenancy.MultiTenancyMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext()
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.RequestLocalization.AbpRequestLocalizationMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext()
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
  • Steps to reproduce the issue:"
  • Login to the web app
  • Logout from the web app using the menu/logout

Expected: The user should be logged out Actual: This exception is shown when the user is directed to https://localhost:44357/Account/Logout

We're not using anything custom for auth, just the built-ins.


11 Answer(s)
  • User Avatar
    0
    onurpicakci created

    Hi, can you check the configurations and module dependencies in the webModule of your application? The error seems to be related to this.

  • User Avatar
    0
    [DependsOn(
        typeof(CabMDHttpApiModule),
        typeof(CabMDHttpApiClientModule),
        typeof(AbpAspNetCoreAuthenticationOpenIdConnectModule),
        typeof(AbpAspNetCoreMvcClientModule),
        typeof(AbpAutofacModule),
        typeof(AbpCachingStackExchangeRedisModule),
        typeof(AbpFeatureManagementWebModule),
        typeof(AbpAccountAdminWebModule),
        typeof(AbpHttpClientIdentityModelWebModule),
        typeof(AbpIdentityWebModule),
        typeof(AbpAuditLoggingWebModule),
        typeof(AbpAspNetCoreMvcUiLeptonXThemeModule),
        typeof(SaasHostWebModule),
        typeof(AbpOpenIddictProWebModule),
        typeof(LanguageManagementWebModule),
        typeof(TextTemplateManagementWebModule),
        typeof(AbpSwashbuckleModule),
        typeof(AbpAspNetCoreSerilogModule),
        typeof(AbpPaymentPayuWebModule),
        typeof(AbpPaymentTwoCheckoutWebModule),
        typeof(AbpPaymentWebModule),
        typeof(FileManagementWebModule),
        typeof(DocsWebModule),
        typeof(CabMDReportingModule),
        typeof(CmsKitProWebModule),
        typeof(AbpBlobStoringModule),
        typeof(AbpTextTemplatingScribanModule)
    )]
    
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    We have an example you can check: https://github.com/abpframework/abp-samples/tree/master/Ids2OpenId

    BTW, can you share the full logs?(webapp & authserver)

  • User Avatar
    0

    Yea, I followed the example I think along with the migration docs.

    That project isn't using LeptonX, which we are.

    Here are the Log files you asked for.

  • User Avatar
    0

    Here's the auth module def:

    DependsOn(
            typeof(AbpAutofacModule),
            typeof(AbpCachingStackExchangeRedisModule),
            typeof(AbpAspNetCoreSerilogModule),
            typeof(AbpAccountPublicWebOpenIddictModule),
            typeof(AbpAspNetCoreMvcUiLeptonXThemeModule),
            typeof(AbpAccountPublicApplicationModule),
            typeof(AbpDistributedLockingModule),
            typeof(CabMDEntityFrameworkCoreModule)
            )]
        public class CabMDAuthServerModule : AbpModule
        {
            private static X509Certificate2 GetSigningCertificate(IConfiguration configuration)
            {
                // try thumbprint first, most secure
                // Note: You need to make sure WEBSITE_LOAD_CERTIFICATES={thumbprint} is on the Azure settings or
                // the cert won't be found. See: https://learn.microsoft.com/en-us/azure/app-service/configure-ssl-certificate-in-code
                var certThumbprint = configuration.GetValue<string>("SigningCertificate:Thumbprint") ?? string.Empty;
                if (!string.IsNullOrEmpty(configuration.GetValue<string>("SigningCertificate:Thumbprint")))
                {
                    using var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
                    var validOnly = false;
                    certStore.Open(OpenFlags.ReadOnly);
    
                    var certCollection = certStore.Certificates.Find(
                                                X509FindType.FindByThumbprint,
                                                certThumbprint,
                                                validOnly);
    
                    // Get the first cert with the thumbprint
                    var cert = certCollection.OfType<X509Certificate2>().FirstOrDefault();
    
                    if (cert is null)
                        throw new Exception($"Certificate with thumbprint {certThumbprint} was not found");
    
                    // Use certificate
                    return cert;
                }
                else
                {
                    // try a physical file as fallback, less secure as we need to provide password and the file is static
                    var certPath = configuration.GetValue<string>("SigningCertificate:Path");
                    if (!string.IsNullOrEmpty(certPath) && File.Exists(certPath))
                    {
                        return new X509Certificate2(certPath, configuration.GetValue<string>("SigningCertificate:Password"));
                    }
                    else
                    {
                        throw new Exception($"Certificate with SigningCertificate:Path '{certPath}' was not found");
                    }
                }
            }
    
            public override void PreConfigureServices(ServiceConfigurationContext context)
            {
                var hostingEnvironment = context.Services.GetHostingEnvironment();
                var configuration = context.Services.GetConfiguration();
    
                PreConfigure<OpenIddictBuilder>(builder =>
                {
                    builder.AddValidation(options =>
                    {
                        options.AddAudiences("CabMD");
                        options.UseLocalServer();
                        options.UseAspNetCore();
                    });
                });
    
                if (!hostingEnvironment.IsDevelopment())
                {
                    PreConfigure<AbpOpenIddictAspNetCoreOptions>(options =>
                    {
                        options.AddDevelopmentEncryptionAndSigningCertificate = false;
                    });
    
                    PreConfigure<OpenIddictServerBuilder>(builder =>
                    {
                        builder.AddSigningCertificate(GetSigningCertificate(configuration));
                        builder.AddEncryptionCertificate(GetSigningCertificate(configuration));
                        builder.SetIssuer(new Uri(configuration["AuthServer:Authority"]));
                    });
                }
            }
    
            public override void ConfigureServices(ServiceConfigurationContext context)
            {
                var hostingEnvironment = context.Services.GetHostingEnvironment();
                var configuration = context.Services.GetConfiguration();
    
                if (!Convert.ToBoolean(configuration["App:DisablePII"]))
                {
                    Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
                }
    
                if (!Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]))
                {
                    Configure<OpenIddictServerAspNetCoreOptions>(options =>
                    {
                        options.DisableTransportSecurityRequirement = true;
                    });
                }
    
                context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
    
                Configure<AbpLocalizationOptions>(options =>
                {
                    options.Resources
                        .Get<CabMDResource>()
                        .AddBaseTypes(
                            typeof(AbpUiResource)
                        );
                });
    
                Configure<AbpBundlingOptions>(options =>
                {
                    options.StyleBundles.Configure(
                        LeptonXThemeBundles.Styles.Global,
                        bundle =>
                        {
                            bundle.AddFiles("/global-styles.css");
                        }
                    );
                });
    
                Configure<AbpAuditingOptions>(options =>
                {
                    //options.IsEnabledForGetRequests = true;
                    options.ApplicationName = "AuthServer";
                });
    
                if (hostingEnvironment.IsDevelopment())
                {
                    Configure<AbpVirtualFileSystemOptions>(options =>
                    {
                        options.FileSets.ReplaceEmbeddedByPhysical<CabMDDomainSharedModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}CabMD.Domain.Shared", Path.DirectorySeparatorChar)));
                        options.FileSets.ReplaceEmbeddedByPhysical<CabMDDomainModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}CabMD.Domain", Path.DirectorySeparatorChar)));
                    });
                }
    
                Configure<AppUrlOptions>(options =>
                {
                    options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"];
                    options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"].Split(','));
                });
    
                Configure<AbpBackgroundJobOptions>(options =>
                {
                    options.IsJobExecutionEnabled = false;
                });
    
                Configure<AbpDistributedCacheOptions>(options =>
                {
                    options.KeyPrefix = "CabMD:";
                });
    
                var dataProtectionBuilder = context.Services.AddDataProtection().SetApplicationName("CabMD");
                if (!hostingEnvironment.IsDevelopment())
                {
                    var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
                    dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "CabMD-Protection-Keys");
                }
    
                context.Services.AddSingleton<IDistributedLockProvider>(sp =>
                {
                    var connection = ConnectionMultiplexer
                        .Connect(configuration["Redis:Configuration"]);
                    return new RedisDistributedSynchronizationProvider(connection.GetDatabase());
                });
    
                context.Services.AddCors(options =>
                {
                    options.AddDefaultPolicy(builder =>
                    {
                        builder
                            .WithOrigins(
                                configuration["App:CorsOrigins"]
                                    .Split(",", StringSplitOptions.RemoveEmptyEntries)
                                    .Select(o => o.RemovePostFix("/"))
                                    .ToArray()
                            )
                            .WithAbpExposedHeaders()
                            .SetIsOriginAllowedToAllowWildcardSubdomains()
                            .AllowAnyHeader()
                            .AllowAnyMethod()
                            .AllowCredentials();
                    });
                });
    
                context.Services.AddAuthentication()
                    .AddGoogle(GoogleDefaults.AuthenticationScheme, _ => { })
                    .WithDynamicOptions<GoogleOptions, GoogleHandler>(
                        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";
                    })
                    .WithDynamicOptions<MicrosoftAccountOptions, MicrosoftAccountHandler>(
                        MicrosoftAccountDefaults.AuthenticationScheme,
                        options =>
                        {
                            options.WithProperty(x => x.ClientId);
                            options.WithProperty(x => x.ClientSecret, isSecret: true);
                        }
                    )
                    .AddTwitter(TwitterDefaults.AuthenticationScheme, options => options.RetrieveUserDetails = true)
                    .WithDynamicOptions<TwitterOptions, TwitterHandler>(
                        TwitterDefaults.AuthenticationScheme,
                        options =>
                        {
                            options.WithProperty(x => x.ConsumerKey);
                            options.WithProperty(x => x.ConsumerSecret, isSecret: true);
                        }
                    );
    
                context.Services.Configure<AbpAccountOptions>(options =>
                {
                    options.TenantAdminUserName = "admin";
                    options.ImpersonationTenantPermission = SaasHostPermissions.Tenants.Impersonation;
                    options.ImpersonationUserPermission = IdentityPermissions.Users.Impersonation;
                });
    
                Configure<LeptonXThemeOptions>(options =>
                {
                    options.DefaultStyle = LeptonXStyleNames.System;
                });
            }
    
            public override void OnApplicationInitialization(ApplicationInitializationContext context)
            {
                var app = context.GetApplicationBuilder();
                var env = context.GetEnvironment();
    
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
    
                app.UseAbpRequestLocalization();
    
                if (!env.IsDevelopment())
                {
                    app.UseErrorPage();
                    app.UseHsts();
                    app.UseHttpsRedirection();
                }
    
                app.UseCorrelationId();
                app.UseStaticFiles();
                app.UseRouting();
                app.UseCors();
                app.UseAuthentication();
                app.UseAbpOpenIddictValidation();
    
                if (MultiTenancyConsts.IsEnabled)
                {
                    app.UseMultiTenancy();
                }
    
                app.UseUnitOfWork();
                app.UseAuthorization();
    
                app.UseAuditing();
                app.UseAbpSerilogEnrichers();
                app.UseConfiguredEndpoints();
    
                if (!env.IsDevelopment())
                {
                    app.Use((httpContext, next) =>
                    {
                        httpContext.Request.Scheme = "https";
                        return next();
                    });
                }
            }
        }
    
  • User Avatar
    0

    Here's the web module def:

    [DependsOn(
        typeof(CabMDHttpApiModule),
        typeof(CabMDHttpApiClientModule),
        typeof(AbpAspNetCoreAuthenticationOpenIdConnectModule),
        typeof(AbpAspNetCoreMvcClientModule),
        typeof(AbpAutofacModule),
        typeof(AbpCachingStackExchangeRedisModule),
        typeof(AbpFeatureManagementWebModule),
        typeof(AbpAccountAdminWebModule),
        typeof(AbpHttpClientIdentityModelWebModule),
        typeof(AbpIdentityWebModule),
        typeof(AbpAuditLoggingWebModule),
        typeof(AbpAspNetCoreMvcUiLeptonXThemeModule),
        typeof(SaasHostWebModule),
        typeof(AbpOpenIddictProWebModule),
        typeof(LanguageManagementWebModule),
        typeof(TextTemplateManagementWebModule),
        typeof(AbpSwashbuckleModule),
        typeof(AbpAspNetCoreSerilogModule),
        typeof(AbpPaymentPayuWebModule),
        typeof(AbpPaymentTwoCheckoutWebModule),
        typeof(AbpPaymentWebModule),
        typeof(FileManagementWebModule),
        typeof(DocsWebModule),
        typeof(CabMDReportingModule),
        typeof(CmsKitProWebModule),
        typeof(AbpBlobStoringModule),
        typeof(AbpTextTemplatingScribanModule)
    )]
    public class CabMDWebModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            var hostingEnvironment = context.Services.GetHostingEnvironment();
            var configuration = context.Services.GetConfiguration();
    
            ConfigureBundles();
            ConfigurePages();
            ConfigureCache();
            ConfigureRedis(context, configuration, hostingEnvironment);
            ConfigureUrls(configuration);
            ConfigureAuthentication(context, configuration);
            ConfigureAutoMapper();
            ConfigureVirtualFileSystem(hostingEnvironment);
            ConfigureNavigationServices(configuration);
            ConfigureSwaggerServices(context.Services);
            ConfigureMultiTenancy();
            ConfigureBackgroundJobs(context, configuration);
            ConfigurePayment();
            ConfigureKendo(context.Services);
            ConfigureReporting(context, configuration);
            ConfigurePwnedPasswords(context.Services);
            ConfigureMiniProfiler(configuration, context.Services);
            ConfigureJsonSerialization();
            ConfigureBlobStorage();
            ConfigureLayoutChanges(configuration);
            //ConfigureHealthChecks(context, configuration);
        }
    
        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            var app = context.GetApplicationBuilder();
            var env = context.GetEnvironment();
    
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
    
            app.UseAbpRequestLocalization();
    
            if (!env.IsDevelopment())
            {
                app.UseErrorPage();
            }
            app.UseCors("TelerikReportingCorsPolicy");
    
            app.UseStaticFiles();
            app.UseRouting();
            app.UseAuthentication();
    
            if (MultiTenancyConsts.IsEnabled)
            {
                app.UseMultiTenancy();
            }
    
            app.UseAuthorization();
            if (bool.Parse(context.GetConfiguration()["App:EnableMiniProfiler"]))
            {
                app.UseMiniProfiler();
            }
    
            if (BackgroundJobConsts.IsEnabled)
            {
                app.UseHangfireDashboard("/hangfire", new DashboardOptions
                {
                    AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter() }
                });
            }
    
            app.UseSwagger();
            app.UseAbpSwaggerUI(options =>
            {
                options.SwaggerEndpoint("/swagger/v1/swagger.json", "CabMD API");
            });
            app.UseAuditing();
            app.UseAbpSerilogEnrichers();
            app.UseConfiguredEndpoints();
        }
    
        public override void PreConfigureServices(ServiceConfigurationContext context)
        {
            context.Services.PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options =>
            {
                options.AddAssemblyResource(
                    typeof(CabMDResource),
                    typeof(CabMDDomainSharedModule).Assembly,
                    typeof(CabMDApplicationContractsModule).Assembly,
                    typeof(CabMDWebModule).Assembly
                );
            });
        }
    
        private static void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
        {
            context.Services.AddAuthentication(options =>
                {
                    options.DefaultScheme = "Cookies";
                    options.DefaultChallengeScheme = "oidc";
                })
                .AddCookie("Cookies", options =>
                {
                    options.ExpireTimeSpan = TimeSpan.FromDays(365);
                })
                .AddAbpOpenIdConnect("oidc", options =>
                {
                    options.Authority = configuration["AuthServer:Authority"];
                    options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]); ;
                    options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
    
                    options.ClientId = configuration["AuthServer:ClientId"];
                    options.ClientSecret = configuration["AuthServer:ClientSecret"];
    
                    options.UsePkce = true; // Add this line
                    options.SaveTokens = true;
                    options.GetClaimsFromUserInfoEndpoint = true;
    
                    options.Scope.Add("roles");
                    options.Scope.Add("email");
                    options.Scope.Add("phone");
                    options.Scope.Add("CabMD");
                });
        }
    
        private static void ConfigureHealthChecks(ServiceConfigurationContext context, IConfiguration configuration)
        {
            if (configuration.GetValue("HealthChecks:HealthChecksEnabled", false))
            {
                context.Services.AddCabHealthChecks(configuration.GetConnectionString("Default"));
            }
        }
    
        private static void ConfigureKendo(IServiceCollection services)
        {
            services.AddKendo();
        }
    
        private static void ConfigureMiniProfiler(IConfiguration configuration, IServiceCollection services)
        {
            if (configuration.GetValue("App:EnableMiniProfiler", false))
            {
                services.AddMiniProfiler(options =>
                {
                    options.RouteBasePath = "/mp";
                    options.SqlFormatter = new StackExchange.Profiling.SqlFormatters.VerboseSqlServerFormatter();
                    options.IgnoredPaths.Add("/elmah");
                    options.IgnoredPaths.Add(".less");
                    options.TrackConnectionOpenClose = false;
                    options.PopupShowTimeWithChildren = true;
                    options.Storage = new RedisStorage(configuration["Redis:Configuration"]);
                }).AddEntityFramework();
            }
        }
    
        /// <summary>
        /// Adds the PwnedPasswords client in DI so we can check during user registration
        /// </summary>
        /// <param name="services"></param>
        private static void ConfigurePwnedPasswords(IServiceCollection services)
        {
            // see: https://blog.elmah.io/avoid-password-reuse-with-pwned-passwords-and-asp-net-core/
    
            services.AddPwnedPasswordHttpClient(minimumFrequencyToConsiderPwned: 1)
                .AddTransientHttpErrorPolicy(p => p.RetryAsync(3))
                .AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(2)));
        }
    
        private static void ConfigureRedis(
            ServiceConfigurationContext context,
            IConfiguration configuration,
            IWebHostEnvironment hostingEnvironment)
        {
            var dataProtectionBuilder = context.Services.AddDataProtection().SetApplicationName("CabMD");
            if (!hostingEnvironment.IsDevelopment())
            {
                var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
                dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "CabMD-Protection-Keys");
            }
    
            context.Services.AddSingleton<IDistributedLockProvider>(sp =>
            {
                var connection = ConnectionMultiplexer
                    .Connect(configuration["Redis:Configuration"]);
                return new RedisDistributedSynchronizationProvider(connection.GetDatabase());
            });
        }
    
        private static void ConfigureReporting(ServiceConfigurationContext context, IConfiguration configuration)
        {
            context.Services.Configure<IISServerOptions>(options => { options.AllowSynchronousIO = true; });
            context.Services.AddScoped<IReportSourceResolver, CabMDReportSourceResolver>();
            context.Services.AddSingleton<IReportServiceConfiguration>(sp =>
                new ReportServiceConfiguration
                {
                    ReportingEngineConfiguration = configuration,
                    HostAppId = "ReportingCore3App",
                    Storage = new FileStorage(),
                    ReportSourceResolver = sp.GetRequiredService<IReportSourceResolver>()
                });
            context.Services.AddCors(o => o.AddPolicy("TelerikReportingCorsPolicy", builder =>
            {
                builder.AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader();
            }));
            context.Services.AddControllers().AddNewtonsoftJson(opt =>
            {
                opt.SerializerSettings.ContractResolver = new ApiHeaderJsonContractResolver(new ApiHeaderJsonNamingStrategyOptions
                {
                    DefaultStrategy = new PascalCaseNamingStrategy(),
                    HeaderName = "json-naming-strategy",
                    HttpContextAccessorProvider = context.Services.BuildServiceProvider().GetService<IHttpContextAccessor>,
                    NamingStrategies = new Dictionary<string, NamingStrategy>
                    {
                        {"camelcase", new CamelCaseNamingStrategy() },
                        {"snakecase", new SnakeCaseNamingStrategy() },
                        {"pascalcase", new PascalCaseNamingStrategy() }
                    }
                }, context.Services.BuildServiceProvider().GetService<IMemoryCache>);
            }).AddJsonOptions(options =>
            {
            });
            context.Services.AddRazorPages().AddNewtonsoftJson();
        }
    
        private static void ConfigureSwaggerServices(IServiceCollection services)
        {
            services.AddSwaggerGen(
                options =>
                {
                    options.SwaggerDoc("v1", new OpenApiInfo { Title = "CabMD API", Version = "v1" });
                    options.DocInclusionPredicate((docName, description) => true);
                    options.CustomSchemaIds(type => type.FullName);
                }
            );
        }
    
        private void ConfigureAutoMapper()
        {
            Configure<AbpAutoMapperOptions>(options =>
            {
                options.AddMaps<CabMDWebModule>();
            });
        }
    
        private void ConfigureBackgroundJobs(ServiceConfigurationContext context, IConfiguration configuration)
        {
            Configure<AbpBackgroundJobOptions>(options => options.IsJobExecutionEnabled = BackgroundJobConsts.IsEnabled);
            Configure<AbpBackgroundWorkerOptions>(options => options.IsEnabled = BackgroundJobConsts.IsEnabled);
    
            if (BackgroundJobConsts.IsEnabled)
            {
                context.Services.AddHangfire(config =>
                {
                    config.UseSqlServerStorage(configuration.GetConnectionString("Default"));
                });
                context.Services.AddHangfireServer();
            }
        }
    
        private void ConfigureBlobStorage()
        {
            Configure<AbpBlobStoringOptions>(options =>
            {
                options.Containers.ConfigureDefault(container =>
                {
                    container.UseDatabase();
                });
            });
        }
    
        private void ConfigureBundles()
        {
            Configure<AbpBundlingOptions>(options =>
            {
                options.StyleBundles.Configure(
                    LeptonXThemeBundles.Styles.Global,
                    bundle =>
                    {
                        bundle.AddFiles("/global-styles.css");
                    }
                );
            });
        }
    
        private void ConfigureCache()
        {
            Configure<AbpDistributedCacheOptions>(options =>
            {
                options.KeyPrefix = "CabMD:";
            });
        }
    
        private void ConfigureJsonSerialization()
        {
            Configure<AbpJsonOptions>(options =>
            {
                //options.UseHybridSerializer = false;
            });
            Configure<AbpSystemTextJsonSerializerOptions>(options =>
            {
                ////options.JsonSerializerOptions.Converters.Add(new JsonNonStringKeyDictionaryConverterFactory());
                //options.JsonSerializerOptions.Converters.Add(new DiagnosticCodes.Diagnostic_Code.Diagnostic_CodeSystemTextJsonConverter());
                //options.JsonSerializerOptions.Converters.Add(new MasterNumbers.Master_Number.Master_NumberSystemTextJsonConverter());
                //options.JsonSerializerOptions.Converters.Add(new CabMD.Patients.Province_Code.Province_CodeSystemTextJsonConverter());
                CabMDJsonSerializationOptions.SetConverters(options.JsonSerializerOptions);
            });
            //Configure<AbpNewtonsoftJsonSerializerOptions>(options =>
            //{
            //    options.Converters.Add<AbpJsonIsoDateTimeConverter>();
            //});
        }
    
        private void ConfigureLayoutChanges(IConfiguration configuration)
        {
            Configure<AbpBundlingOptions>(options =>
            {
                options.StyleBundles.Configure(LeptonXThemeBundles.Styles.Global,
                    bundle =>
                    {
                        bundle.AddContributors(typeof(KendoStyleContributor));
                    });
                options
                    .StyleBundles
                    .Get(StandardBundles.Styles.Global)
                    .Contributors.Remove<FontAwesomeStyleContributor>(); // Do this so we can use pro kit
            });
    
            Configure<AbpLayoutHookOptions>(options =>
            {
                options.Add(
                    LayoutHooks.Head.Last, //The hook name
                    typeof(KendoViewComponent) //The component to add
                );
    
                options.Add(LayoutHooks.Body.Last, typeof(KendoDeferredViewComponent));
    
                options.Add(
                    LayoutHooks.Head.Last, //The hook name
                    typeof(FontAwesomeViewComponent) // Add the pro kit
                );
    
                if (configuration.GetValue<bool>("Intercom:Enabled", false))
                {
                    options.Add(
                        LayoutHooks.Head.First,
                        typeof(IntercomViewComponent));
                }
    
                if (configuration.GetValue<bool>("App:EnableMiniProfiler", false))
                {
                    options.Add(
                        LayoutHooks.Body.Last,
                        typeof(MiniProfilerViewComponent));
                }
            });
        }
    
        private void ConfigureMultiTenancy()
        {
            Configure<AbpMultiTenancyOptions>(options => { options.IsEnabled = MultiTenancyConsts.IsEnabled; });
        }
    
        private void ConfigureNavigationServices(IConfiguration configuration)
        {
            Configure<AbpNavigationOptions>(options =>
            {
                options.MenuContributors.Add(new CabMDMenuContributor(configuration));
            });
    
            Configure<AbpToolbarOptions>(options =>
            {
                options.Contributors.Add(new CabMDToolbarContributor());
            });
        }
    
        private void ConfigurePages()
        {
            Configure<RazorPagesOptions>(options =>
            {
                options.Conventions.AuthorizePage("/HostDashboard", CabMDPermissions.Dashboard.Host);
                options.Conventions.AuthorizePage("/TenantDashboard", CabMDPermissions.Dashboard.Tenant);
                options.Conventions.AuthorizePage("/Plans/Index", CabMDPermissions.Plans.Default);
                options.Conventions.AuthorizePage("/CareProviders/Index", CabMDPermissions.CareProviders.Default);
                options.Conventions.AuthorizePage("/MasterNumbers/Index", CabMDPermissions.MasterNumbers.Default);
                options.Conventions.AuthorizePage("/DiagnosticCodes/Index", CabMDPermissions.DiagnosticCodes.Default);
                options.Conventions.AuthorizePage("/Services/Index", CabMDPermissions.Services.Default);
            });
    
            Configure<RouteOptions>(options =>
            {
                options.ConstraintMap.Add("claimstate", typeof(ClaimStateConstraint));
                options.ConstraintMap.Add("patientid", typeof(PatientIdConstraint));
            });
        }
    }
    
  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    You can try to add Volo.Abp.Account.Pro.Public.Web.Impersonation package to the Web project.

    And add typeof(AbpAccountPublicWebImpersonationModule) to the Web module class.

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Add AccountController to the Web project

    public class AccountController : AbpAccountImpersonationChallengeAccountController
    {
    
    }
    
    
  • User Avatar
    0

    No change.

  • User Avatar
    0
    liangshiwei created
    Support Team Fullstack Developer

    Hi,

    Can you share a project that can reproduce the problem? shiwei.liang@volosoft.com I will check it. thanks.

  • User Avatar
    0

    Just in case others find this thread, the issue for us was that we still had some packages from before our Lepton to LeptonX migration - Volo.Abp.LeptonTheme.*. Once we removed those six packages, it started working normally.

Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
Do you need assistance from an ABP expert?
Schedule a Meeting
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v9.2.0-preview. Updated on March 13, 2025, 04:08