-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Description
Is there an existing issue for this?
- I have searched the existing issues
Description
-
The document description is not clear, it is not enough to just set IsEnabled to true in the
WebRemoteDynamicClaimsPrincipalributorOptionsconfiguration,WebRemoteDynamicClaimsPrincipalContributorwill not be triggered. -
Even if
WebRemoteDynamicClaimsPrincipalContributoris triggered,RemoteRefreshUrlwill not be called because they use the same cache,IdentityDynamicClaimsPrincipalContributoris triggered preferentially, andWebRemoteDynamicClaimsPrincipalContributorreturns the cached value directly after it is triggered, thus not requestingRemoteRefreshUrl. -
Missing other services custom claim.
Reproduction Steps
- Add a dependency on the
AbpAspNetCoreAuthenticationJwtBearerModulemodule in the xxxModule and add the following configuration to enable theWebRemoteDynamicsPrincipalContributor.
[DependsOn(typeof(AbpAspNetCoreAuthenticationJwtBearerModule))]
public class xxxModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<WebRemoteDynamicClaimsPrincipalContributorOptions>(options =>
{
options.IsEnabled = true;
});
}
}- Rewrite the
AbpClaimsPrincipalFactoryservice, without changing the actual logic, just to add log printing
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IAbpClaimsPrincipalFactory), typeof(AbpClaimsPrincipalFactory), typeof(CustomClaimsPrincipalFactory))]
public class CustomClaimsPrincipalFactory : AbpClaimsPrincipalFactory
{
public CustomClaimsPrincipalFactory(IServiceProvider serviceProvider, IOptions<AbpClaimsPrincipalFactoryOptions> abpClaimOptions) : base(serviceProvider, abpClaimOptions)
{
}
public override async Task<ClaimsPrincipal> InternalCreateAsync(AbpClaimsPrincipalFactoryOptions options, ClaimsPrincipal? existsClaimsPrincipal = null, bool isDynamic = false)
{
var claimsPrincipal = existsClaimsPrincipal ?? new ClaimsPrincipal(new ClaimsIdentity(
AuthenticationType,
AbpClaimTypes.UserName,
AbpClaimTypes.Role));
var context = new AbpClaimsPrincipalContributorContext(claimsPrincipal, ServiceProvider);
var logger = ServiceProvider.GetRequiredService<ILogger<CustomClaimsPrincipalFactory>>();
if (!isDynamic)
{
logger.LogInformation("DynamicClaims no enabled");
foreach (var contributorType in options.Contributors)
{
logger.LogInformation("Contributor call {ContributorName}", contributorType.Name);
var contributor = (IAbpClaimsPrincipalContributor)ServiceProvider.GetRequiredService(contributorType);
await contributor.ContributeAsync(context);
}
}
else
{
logger.LogInformation("DynamicClaims enabled");
foreach (var contributorType in options.DynamicContributors)
{
logger.LogInformation("DynamicContributor call {DynamicContributorName}", contributorType.Name);
var contributor = (IAbpDynamicClaimsPrincipalContributor)ServiceProvider.GetRequiredService(contributorType);
await contributor.ContributeAsync(context);
}
}
return context.ClaimsPrincipal;
}
}- Rewrite the
DynamicClaimsAppServiceservice, again just add logs
[RemoteService(IsEnabled = false)]
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IDynamicClaimsAppService), typeof(DynamicClaimsAppService), typeof(CustomDynamicClaimsAppService))]
public class CustomDynamicClaimsAppService : DynamicClaimsAppService
{
public CustomDynamicClaimsAppService(IdentityDynamicClaimsPrincipalContributorCache identityDynamicClaimsPrincipalContributorCache, IAbpClaimsPrincipalFactory abpClaimsPrincipalFactory, ICurrentPrincipalAccessor principalAccessor) : base(identityDynamicClaimsPrincipalContributorCache, abpClaimsPrincipalFactory, principalAccessor)
{
}
[Authorize]
public override async Task RefreshAsync()
{
Logger.LogInformation("Trigger dynamicClaims refresh");
await IdentityDynamicClaimsPrincipalContributorCache.ClearAsync(CurrentUser.GetId(), CurrentUser.TenantId);
await AbpClaimsPrincipalFactory.CreateDynamicAsync(PrincipalAccessor.Principal);
}
}- Login and call the web api, observe the log print
Expected behavior
WebRemoteDynamicClaimsPrincipalContributor should be triggered and log should be printed.
Actual behavior
Dynamic claims are only triggered when IdentityDynamicClaimsPrincipalContributor is triggered and OpenIddictClaimsPrincipalContributor is also triggered.
The configuration of AbpClaimsPrincipalFactoryOptions is also needed to be added in the PreConfigureServices method in order to truly enable the WebRemoteDynamicsPrincipalContributor.
[DependsOn(typeof(AbpAspNetCoreAuthenticationJwtBearerModule))]
public class xxxModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<WebRemoteDynamicClaimsPrincipalContributorOptions>(options =>
{
options.IsEnabled = true;
});
PreConfigure<AbpClaimsPrincipalFactoryOptions>(options =>
{
options.IsRemoteRefreshEnabled = true;
});
}
}
Because IdentityDynamicClaimsPrincipalContributor is triggered preferentially the CreateAsync method of UserClaimsPrincipalFactory is called in the IdentityDynamicClaimsPrincipalContributorCache and the cache of the dynamic claims is set, this is also why the OpenIddictClaimsPrincipalContributor is triggered.
When the WebRemoteDynamicClaimsPrincipalContributor is triggered, cache is not empty, so it returns directly, which also causes the loss of custom claims added by other services.
Regression?
The same is true in version 9.x.
Known Workarounds
No response
Version
10.0.2
User Interface
Common (Default)
Database Provider
EF Core (Default)
Tiered or separate authentication server
Separate Auth Server
Operation System
macOS
Other information
No response