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.
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.
Hi, I sent the project source code to your e-mail address.
It didn't work. The new solution is created via OpenIddict and everything works smoothly there. But our application uses IdentityServer4.
Hi,
I tried 2 scenarios.
[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)
Do I need to remove app.UseDynamicClaims
from all service projects and add it only to the Web project? Did I get right?
Hi,
I sent you the log files by e-mail.
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.
Yes, adding the module fixed it, but why am I adding the Identity EFCore module? Because there was no need to add this in other similar projects.
Identity is another project and I manage it in database.
[ERR] An exception was thrown while activating Odin.Countries.CountryController -> Odin.Countries.CountryAppService -> Odin.Users.AppUserLookupService -> Volo.Abp.Identity.IdentityUserRepositoryExternalUserLookupServiceProvider.
Autofac.Core.DependencyResolutionException: An exception was thrown while activating Odin.Countries.CountryController -> Odin.Countries.CountryAppService -> Odin.Users.AppUserLookupService -> Volo.Abp.Identity.IdentityUserRepositoryExternalUserLookupServiceProvider.
---> Autofac.Core.DependencyResolutionException: None of the constructors found with 'Volo.Abp.Autofac.AbpAutofacConstructorFinder' on type 'Volo.Abp.Identity.IdentityUserRepositoryExternalUserLookupServiceProvider' can be invoked with the available services and parameters:
Cannot resolve parameter 'Volo.Abp.Identity.IIdentityUserRepository userRepository' of constructor 'Void .ctor(Volo.Abp.Identity.IIdentityUserRepository, Microsoft.AspNetCore.Identity.ILookupNormalizer)'.
at Autofac.Core.Activators.Reflection.ReflectionActivator.GetAllBindings(ConstructorBinder[] availableConstructors, IComponentContext context, IEnumerable`1 parameters)
at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)
at Autofac.Core.Activators.Reflection.ReflectionActivator.<ConfigurePipeline>b__11_0(ResolveRequestContext ctxt, Action`1 next)
at Autofac.Core.Resolving.Middleware.DisposalTrackingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
at Autofac.Builder.RegistrationBuilder`3.<>c__DisplayClass41_0.<PropertiesAutowired>b__0(ResolveRequestContext ctxt, Action`1 next)
at Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
--- End of inner exception stack trace ---
at Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
at Autofac.Core.Resolving.Middleware.SharingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
at Autofac.Core.Resolving.Middleware.CircularDependencyDetectorMiddleware.Execute(ResolveRequestContext context, Action`1 next)
at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, ResolveRequest request)
at Autofac.Core.Resolving.ResolveOperation.ExecuteOperation(ResolveRequest request)
at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance)
at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable`1 parameters)
at Microsoft.AspNetCore.Mvc.Controllers.ServiceBasedControllerActivator.Create(ControllerContext actionContext)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
2021-10-18 13:48:37.281 +03:00 [ERR] ---------- Exception Data ----------
ActivatorChain = Odin.Countries.CountryController -> Odin.Countries.CountryAppService -> Odin.Users.AppUserLookupService -> Volo.Abp.Identity.IdentityUserRepositoryExternalUserLookupServiceProvider
Hello Team,
I am getting depend error in AppUserLookupService
class.I did it based on the sample projects, but I could not solve the error.
public interface IAppUserLookupService : IUserLookupService<AppUser>
{
}
public class AppUserLookupService : UserLookupService<AppUser, IAppUserRepository>, IAppUserLookupService
{
public AppUserLookupService(
IAppUserRepository userRepository,
IUnitOfWorkManager unitOfWorkManager)
: base(
userRepository,
unitOfWorkManager
)
{
}
protected override AppUser CreateUser(IUserData externalUser)
{
return new AppUser(externalUser);
}
}
public interface IAppUserRepository : IBasicRepository<AppUser, Guid>, IUserRepository<AppUser>
{
Task<List<AppUser>> GetUsersAsync(int maxCount, string filter, CancellationToken cancellationToken = default);
}
public class EfCoreAppUserRepository : EfCoreUserRepositoryBase<OdinDbContext, AppUser>, IAppUserRepository
{
public EfCoreAppUserRepository(IDbContextProvider<OdinDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public async Task<List<AppUser>> GetUsersAsync(int maxCount, string filter, CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.WhereIf(!string.IsNullOrWhiteSpace(filter), x => x.UserName.Contains(filter))
.Take(maxCount).ToListAsync(cancellationToken);
}
}
}
public class AppUser : AggregateRoot<Guid>, IUser, IUpdateUserData
{
#region Base properties
/* These properties are shared with the IdentityUser entity of the Identity module.
* Do not change these properties through this class. Instead, use Identity module
* services (like IdentityUserManager) to change them.
* So, this properties are designed as read only!
*/
public virtual Guid? TenantId { get; private set; }
public virtual string UserName { get; private set; }
public virtual string Name { get; private set; }
public virtual string Surname { get; private set; }
public virtual string Email { get; private set; }
public virtual bool EmailConfirmed { get; private set; }
public virtual string PhoneNumber { get; private set; }
public virtual bool PhoneNumberConfirmed { get; private set; }
#endregion
/* Add your own properties here. Example:
*
* public virtual string MyProperty { get; set; }
* public string MyProperty { get; set; }
*
* If you add a property and using the EF Core, remember these;
*
* 1. update ArtFlowDbContext.OnModelCreating
* to configure the mapping for your new property
* 2. Update ArtFlowEfCoreEntityExtensionMappings to extend the IdentityUser entity
* and add your new property to the migration.
* 3. Use the Add-Migration to add a new database migration.
* 4. Run the .DbMigrator project (or use the Update-Database command) to apply
* schema change to the database.
*/
protected AppUser()
{
}
public AppUser(IUserData user)
: base(user.Id)
{
TenantId = user.TenantId;
UpdateInternal(user);
}
I added AbpHttpClientIdentityModelModule
and AbpIdentityHttpApiClientModule
modules.
[DependsOn(
typeof(OdinHttpApiModule),
typeof(OdinApplicationModule),
typeof(OdinEntityFrameworkCoreModule),
typeof(OdinCouchbaseModule),
typeof(AbpPermissionManagementDomainIdentityModule),
typeof(RetinaPermissionManagementDomainCcmsModule),
typeof(AbpAutofacModule),
typeof(AbpEventBusRabbitMqModule),
typeof(AbpBackgroundJobsRabbitMqModule),
typeof(AbpAspNetCoreMultiTenancyModule),
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpAspNetCoreMvcUiMultiTenancyModule),
typeof(AbpIdentityAspNetCoreModule),
typeof(AbpSwashbuckleModule),
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpHttpClientIdentityModelModule),
typeof(AbpIdentityHttpApiClientModule),
typeof(AbpPermissionManagementEntityFrameworkCoreModule),
typeof(SaasEntityFrameworkCoreModule)
)]
public class OdinHttpApiHostModule : AbpModule
"IdentityClients": {
"Default": {
"GrantType": "client_credentials",
"ClientId": "OdinService",
"ClientSecret": "1q2w3e*",
"Authority": "https://localhost:44322",
"Scope": "IdentityService"
}
},
I added AbpUsersEntityFrameworkCoreModule
to EFCore
module and I added AbpUsersDomainModule
to DomainModule
module.
Thank you for support.