- ABP Framework version: v8.0.0
- UI Type: MVC
- Database System: EF Core (SQL Server)
- Tiered (for MVC): yes
- Exception message and full stack trace:
- Steps to reproduce the issue:
We use the commercial microservice solution. After upgrading to v8.0.0, we receive authorization errors at the identity and identityserver endpoints in the IdentityService service. When I checked the logs of other services, I noticed that it could not read user and role permissions.
We use Identity Server in AuthServer.
IdentityServiceModule.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Retina.IdentityService.DbMigrations;
using Retina.IdentityService.EntityFramework;
using Retina.Shared.Hosting.Microservices;
using Prometheus;
using Volo.Abp;
using Volo.Abp.Modularity;
using Volo.Abp.Threading;
using Volo.Abp.AspNetCore.Mvc.AntiForgery;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.Google;
using Microsoft.AspNetCore.Authentication.MicrosoftAccount;
using Microsoft.AspNetCore.Authentication.Twitter;
using Microsoft.Extensions.Configuration;
using Retina.Shared.Hosting.AspNetCore.HealthChecks;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Auditing;
using Volo.Abp.Security.Claims;
namespace Retina.IdentityService
{
[DependsOn(
typeof(RetinaSharedHostingMicroservicesModule),
typeof(IdentityServiceEntityFrameworkCoreModule),
typeof(IdentityServiceApplicationModule),
typeof(IdentityServiceHttpApiModule)
)]
public class IdentityServiceHttpApiHostModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
// Enable if you need these
var configuration = context.Services.GetConfiguration();
// var hostingEnvironment = context.Services.GetHostingEnvironment();
JwtBearerConfigurationHelper.Configure(context, "IdentityService");
SwaggerConfigurationHelper.Configure(context, "Identity Service API");
context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.IsDynamicClaimsEnabled = true;
});
Configure<AbpAspNetCoreMvcOptions>(options => { options.ExposeIntegrationServices = true; });
ConfigureAuditLogs();
ConfigureHealthChecks(context.Services, configuration);
ConfigureExternalProviders(context);
}
private void ConfigureHealthChecks(IServiceCollection services, IConfiguration configuration)
{
services.AddRetinaHealthChecks("Identity Api", configuration["ConnectionStrings:IdentityService"]);
}
private void ConfigureAuditLogs()
{
Configure<AbpAuditingOptions>(options => { options.ApplicationName = "Identity Service"; });
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCorrelationId();
app.UseAbpRequestLocalization();
app.UseAbpSecurityHeaders();
app.UseStaticFiles();
app.UseRouting();
// app.UseCors();
app.UseHttpMetrics();
app.UseAuthentication();
app.UseAbpClaimsMap();
app.UseMultiTenancy();
app.UseUnitOfWork();
app.UseDynamicClaims();
app.UseAuthorization();
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Identity Service API");
});
app.UseAbpSerilogEnrichers();
app.UseAuditing();
app.UseConfiguredEndpoints(endpoints => { endpoints.MapMetrics(); });
}
public async override Task OnPostApplicationInitializationAsync(ApplicationInitializationContext context)
{
var env = context.GetEnvironment();
// if (!env.IsDevelopment())
// {
using (var scope = context.ServiceProvider.CreateScope())
{
await scope.ServiceProvider
.GetRequiredService<IdentityServiceDatabaseMigrationChecker>()
.CheckAndApplyDatabaseMigrationsAsync();
}
// }
}
private void ConfigureExternalProviders(ServiceConfigurationContext context)
{
context.Services
.AddDynamicExternalLoginProviderOptions<GoogleOptions>(
GoogleDefaults.AuthenticationScheme,
options =>
{
options.WithProperty(x => x.ClientId);
options.WithProperty(x => x.ClientSecret, isSecret: true);
}
)
.AddDynamicExternalLoginProviderOptions<MicrosoftAccountOptions>(
MicrosoftAccountDefaults.AuthenticationScheme,
options =>
{
options.WithProperty(x => x.ClientId);
options.WithProperty(x => x.ClientSecret, isSecret: true);
}
)
.AddDynamicExternalLoginProviderOptions<TwitterOptions>(
TwitterDefaults.AuthenticationScheme,
options =>
{
options.WithProperty(x => x.ConsumerKey);
options.WithProperty(x => x.ConsumerSecret, isSecret: true);
}
);
}
}
}
AuthServerModule.cs
using System;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Retina.AdministrationService.EntityFrameworkCore;
using Retina.IdentityService.EntityFramework;
using Retina.SaasService.EntityFramework;
using Retina.Shared.Hosting.AspNetCore;
using Prometheus;
using StackExchange.Redis;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.Account.Web;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.Auditing;
using Volo.Abp.BackgroundJobs.RabbitMQ;
using Volo.Abp.Caching;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.Emailing;
using Volo.Abp.EventBus.RabbitMq;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.UI.Navigation.Urls;
using Volo.Abp.VirtualFileSystem;
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http;
using System.Net;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using System.Security.Claims;
using Volo.Abp.IdentityServer;
using IdentityServer4.Configuration;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.AspNetCore.Mvc.AntiForgery;
using Microsoft.IdentityModel.Logging;
using Volo.Abp.Account.Public.Web;
using Microsoft.Extensions.Configuration;
using IdentityServer4.Extensions;
using System.Collections.Generic;
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Google;
using Microsoft.AspNetCore.Authentication.MicrosoftAccount;
using Microsoft.AspNetCore.Authentication.Twitter;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.Identity.Web;
using Retina.Shared.Hosting.AspNetCore.HealthChecks;
using Volo.Abp.Account.Public.Web.ExternalProviders;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonX;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonX.Bundling;
using Volo.Abp.LeptonX.Shared;
using Volo.Abp.Security.Claims;
namespace Retina.AuthServer
{
[DependsOn(
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpEventBusRabbitMqModule),
typeof(AbpAspNetCoreMvcUiLeptonXThemeModule),
typeof(AbpBackgroundJobsRabbitMqModule),
typeof(AbpAccountPublicWebIdentityServerModule),
typeof(AbpAccountPublicApplicationModule),
typeof(AbpAccountPublicHttpApiModule),
typeof(AdministrationServiceEntityFrameworkCoreModule),
typeof(IdentityServiceEntityFrameworkCoreModule),
typeof(SaasServiceEntityFrameworkCoreModule),
typeof(RetinaSharedHostingAspNetCoreModule),
typeof(RetinaSharedLocalizationModule),
typeof(AbpAccountAdminApplicationModule),
typeof(AbpAccountAdminHttpApiModule)
)]
public class RetinaAuthServerModule : AbpModule
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>();
app.Use(async (ctx, next) =>
{
ctx.Request.Scheme = "https";
if (ctx.Request.Headers.ContainsKey("from-ingress"))
{
ctx.SetIdentityServerOrigin(configuration["App:SelfUrl"]);
}
if (ctx.Request.Path.StartsWithSegments("/robots.txt"))
{
var robotsTxtPath = Path.Combine(env.ContentRootPath, "robots.txt");
string output = "User-agent: * \nDisallow: /";
if (File.Exists(robotsTxtPath))
{
output = await File.ReadAllTextAsync(robotsTxtPath);
}
ctx.Response.ContentType = "text/plain";
await ctx.Response.WriteAsync(output);
}
else
{
await next();
}
});
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAbpRequestLocalization();
if (!env.IsDevelopment())
{
app.UseErrorPage();
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseCorrelationId();
app.UseAbpSecurityHeaders();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(DefaultCorsPolicyName);
app.UseCookiePolicy();
app.UseHttpMetrics();
app.UseAuthentication();
app.UseJwtTokenMiddleware();
app.UseMultiTenancy();
app.UseAbpSerilogEnrichers();
app.UseUnitOfWork();
app.UseDynamicClaims();
app.UseIdentityServer();
app.UseAuthorization();
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Account Service API");
options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
options.OAuthClientSecret(configuration["AuthServer:SwaggerClientSecret"]);
});
app.UseAuditing();
app.UseConfiguredEndpoints(endpoints => { endpoints.MapMetrics(); });
}
private void ConfigureSwagger(ServiceConfigurationContext context, IConfiguration configuration)
{
SwaggerConfigurationHelper.ConfigureWithAuth(
context: context,
authority: configuration["AuthServer:Authority"],
scopes: new Dictionary<string, string>
{
/* Requested scopes for authorization code request and descriptions for swagger UI only */
{ "AuthServer", "Account Service API" }
},
apiTitle: "Account Service API"
);
}
}
}
[identity-service_3e0e16ed-9]: [11:19:20 DBG] PermissionStore.GetCacheItemAsync: pn:C,pk:Retina_Web,n:AbpIdentity.OrganizationUnits [identity-service_3e0e16ed-9]: [11:19:20 DBG] Found in the cache: pn:C,pk:Retina_Web,n:AbpIdentity.OrganizationUnits
As seen here, it does not see the caches in the Role and User providers.
But other services work with the same configurations. But there is such an error in the IdentityService service. I would like your support in solving it.
15 Answer(s)
-
0
hi
Can you share the full logs? liming.ma@volosoft.com
Have you tested this case in a new microservice template project?
-
0
Hi,
I sent you the log files by e-mail.
-
0
hi
You can try to remove the
app.UseDynamicClaims
from the ASP NET Core pipeline.https://docs.abp.io/en/abp/latest/Dynamic-Claims
[auth-server_9fe7f5b1-5]: [21:50:00 ERR] ---------- RemoteServiceErrorInfo ---------- [auth-server_9fe7f5b1-5]: { [auth-server_9fe7f5b1-5]: "code": null, [auth-server_9fe7f5b1-5]: "message": "An internal error occurred during your request!", [auth-server_9fe7f5b1-5]: "details": null, [auth-server_9fe7f5b1-5]: "data": {}, [auth-server_9fe7f5b1-5]: "validationErrors": null [auth-server_9fe7f5b1-5]: } [auth-server_9fe7f5b1-5]: [auth-server_9fe7f5b1-5]: [21:50:00 ERR] Nullable object must have a value. [auth-server_9fe7f5b1-5]: System.InvalidOperationException: Nullable object must have a value. [auth-server_9fe7f5b1-5]: at System.Nullable`1.get_Value() [auth-server_9fe7f5b1-5]: at Volo.Abp.Users.CurrentUserExtensions.GetId(ICurrentUser currentUser) [auth-server_9fe7f5b1-5]: at Volo.Abp.Account.DynamicClaimsAppService.RefreshAsync()```
-
0
Do I need to remove
app.UseDynamicClaims
from all service projects and add it only to the Web project? Did I get right? -
0
hi
You can remove it from all projects. then check if the problem solved.
-
0
Hi,
I tried 2 scenarios.
- case: When I removed it from all projects, the same problem continued. I just added this in the Web and Auth project.
- case: When I remove it from all projects, I get the following error.
[web_6c4bc74a-5]: [15:42:43 WRN] Failed to refresh remote claims for user: 26af7673-d0d8-65ba-6dde-39fc9b34793c [web_6c4bc74a-5]: System.Net.Http.HttpRequestException: Response status code does not indicate success: 500 (Internal Server Error). [web_6c4bc74a-5]: at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() [web_6c4bc74a-5]: at Volo.Abp.AspNetCore.Mvc.Client.RemoteDynamicClaimsPrincipalContributorCache.RefreshAsync(Guid userId, Nullable`1 tenantId) [web_6c4bc74a-5]: at Volo.Abp.Security.Claims.RemoteDynamicClaimsPrincipalContributorCacheBase`1.GetAsync(Guid userId, Nullable`1 tenantId) [web_6c4bc74a-5]: at Volo.Abp.Security.Claims.RemoteDynamicClaimsPrincipalContributorBase`2.ContributeAsync(AbpClaimsPrincipalContributorContext context)
-
0
hi
Have you enabled the
IsDynamicClaimsEnabled
? you can set it to default(false
) or remove the configure code.context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options => { options.IsDynamicClaimsEnabled = true; });
Have you tested this case in a new microservice template project?
-
0
It didn't work. The new solution is created via OpenIddict and everything works smoothly there. But our application uses IdentityServer4.
-
0
hi
Can you share your project source code? I need to check it on my local. liming.ma@volosoft.com
-
0
Hi, I sent the project source code to your e-mail address.
-
0
hi
Got it. Can you also share some steps? Thanks
-
0
Hi,
You can perform database migrations with the DbMigrator project and then run the project via tye. You will see the errors I mentioned in Identit Management and Identity Server Management in the Administration menu.
-
0
-
0
Hi,
Thank you very much. It worked when I added the code. What is the purpose of doing this?
Other services do not have this configuration, but it still works.
-
0
The IdentityServerHttpApiHostModule depends on the IdentityServerDomainModule and will change the claim types. We need to disable this behavior.
The other microservices don't need to change.
https://github.com/abpframework/abp/blob/dev/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderExtensions.cs#L47-L53