Ok thank you so much for your quick responses, this resolves my problem.
Have a good one!
Hi,
Yep, this works and all claims and original token are passed.
One more thing I need to ask, in my case I need to modify the token to remove some of the claims I dont want them all to pass. For this, I will decode the jwt token and modify the object, but when reencoding, I will need the encryption key. Where is that stored, or is there a better method to handle this?
Thanks
Hi,
I've added it, and I get these logs:
[09:18:18 ERR] BearerTokenHeader is: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjRDOEEyRUNFRDZGRTc5RjQ3NkM5NDc5RDUwNTgzMTA2REFFQjI2NzQiLCJ4NXQiOiJUSW91enRiLWVmUjJ5VWVkVUZneEJ0cnJKblEiLCJ0eXAiOiJhdCtqd3QifQ.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjQ0MzMyLyIsImV4cCI6MTc1NDU2MTc2NCwiaWF0IjoxNzU0NTU4MTY0LCJhdWQiOlsiQWNjb3VudFNlcnZpY2UiLCJJZGVudGl0eVNlcnZpY2UiLCJBZG1pbmlzdHJhdGlvblNlcnZpY2UiLCJTYWFzU2VydmljZSIsIlNldHRpbmdTZXJ2aWNlIiwiVHJhdmVsbGVyU2VydmljZSIsIkxvY2F0aW9uU2VydmljZSIsIkNvbnRyYWN0U2VydmljZSIsIkNSTVNlcnZpY2UiLCJUYWdTZXJ2aWNlIiwiRXhwb3J0VmFsaWRhdGlvblNlcnZpY2UiLCJSZWZ1bmRTZXJ2aWNlIiwiRmluYW5jZVNlcnZpY2UiLCJSZXBvcnRTZXJ2aWNlIiwiRmlsZVNlcnZpY2UiLCJTU1JTZXJ2aWNlIl0sInNjb3BlIjoiQWRtaW5pc3RyYXRpb25TZXJ2aWNlIEFjY291bnRTZXJ2aWNlIElkZW50aXR5U2VydmljZSBTYWFzU2VydmljZSBTZXR0aW5nU2VydmljZSBUcmF2ZWxsZXJTZXJ2aWNlIExvY2F0aW9uU2VydmljZSBDb250cmFjdFNlcnZpY2UgQ1JNU2VydmljZSBUYWdTZXJ2aWNlIFJlZnVuZFNlcnZpY2UgRXhwb3J0VmFsaWRhdGlvblNlcnZpY2UgRmluYW5jZVNlcnZpY2UgUmVwb3J0U2VydmljZSBGaWxlU2VydmljZSBTU1JTZXJ2aWNlIiwianRpIjoiZmE4YTRkZjMtOGY4OC00YTE4LTlkNzMtZGIyNmU2ZTBiMTNmIiwic3ViIjoiNDNlNjg3OGMtZGNlYi1mZTlhLWZkOTUtM2ExYjc2ZGRmZjU0IiwiUkxTX09yZ2FuaXphdGlvbklkIjoieW91ci1vcmdhbml6YXRpb24taWQiLCJzZXNzaW9uX2lkIjoiNDdiZjMyNmItZmIzOS00Njk2LTk3ZDQtZDI5ZmMwOTI1YWIwIiwidW5pcXVlX25hbWUiOiJhZG1pbiIsIm9pX3Byc3QiOiJXZWJHYXRld2F5X1N3YWdnZXIiLCJvaV9hdV9pZCI6IjEzNGZhN2M4LTQwMDUtOTQzMi0wZDI4LTNhMWI3NmY4NTc2OCIsInByZWZlcnJlZF91c2VybmFtZSI6ImFkbWluIiwiZ2l2ZW5fbmFtZSI6ImFkbWluIiwicm9sZSI6ImFkbWluIiwiZW1haWwiOiJhZG1pbkBhYnAuaW8iLCJlbWFpbF92ZXJpZmllZCI6IkZhbHNlIiwicGhvbmVfbnVtYmVyX3ZlcmlmaWVkIjoiRmFsc2UiLCJjbGllbnRfaWQiOiJXZWJHYXRld2F5X1N3YWdnZXIiLCJvaV90a25faWQiOiJkNzhjYjMyZS01OTMzLTg4NzMtNDA2Ni0zYTFiOTVmZGM2M2YifQ.OA-zR0hqsSxycGjnmcRYq73vVcgyeytmIKh2hhIM1qLIbfvHRMYNY5lKywkO98jg-Tx5fL0B8UyU4ZyzLNgkhGcAnDoSyBSMiRIKwaVBUiQkbbMvuDkXNHMA6GjQPHjkf4uROZknj-zHtCDrhB6GLUlHaipsOV1nEOouzeRiujx-YgaexR2Aovr32kzQ9jsA7N-16mOtY1ehGVbcCtA2AvEq02aj8NdyiVY-sOYAdzoks-mnRUNjSOFkWOkl80b8qn34vs9tKkHp6pHEUsEqYukrd7k87dle_zV1t3BqQ-hKZeU4fL-SqwzG7jaIsRcd-6Ta8hisdp3X8d52CFODEw
[09:18:21 ERR] Getting access token from HTTP context: eyJhbGciOiJSUzI1NiIsImtpZCI6IjRDOEEyRUNFRDZGRTc5RjQ3NkM5NDc5RDUwNTgzMTA2REFFQjI2NzQiLCJ4NXQiOiJUSW91enRiLWVmUjJ5VWVkVUZneEJ0cnJKblEiLCJ0eXAiOiJhdCtqd3QifQ.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjQ0MzMyLyIsImV4cCI6MTc1NDU2MTc2NCwiaWF0IjoxNzU0NTU4MTY0LCJhdWQiOlsiQWNjb3VudFNlcnZpY2UiLCJJZGVudGl0eVNlcnZpY2UiLCJBZG1pbmlzdHJhdGlvblNlcnZpY2UiLCJTYWFzU2VydmljZSIsIlNldHRpbmdTZXJ2aWNlIiwiVHJhdmVsbGVyU2VydmljZSIsIkxvY2F0aW9uU2VydmljZSIsIkNvbnRyYWN0U2VydmljZSIsIkNSTVNlcnZpY2UiLCJUYWdTZXJ2aWNlIiwiRXhwb3J0VmFsaWRhdGlvblNlcnZpY2UiLCJSZWZ1bmRTZXJ2aWNlIiwiRmluYW5jZVNlcnZpY2UiLCJSZXBvcnRTZXJ2aWNlIiwiRmlsZVNlcnZpY2UiLCJTU1JTZXJ2aWNlIl0sInNjb3BlIjoiQWRtaW5pc3RyYXRpb25TZXJ2aWNlIEFjY291bnRTZXJ2aWNlIElkZW50aXR5U2VydmljZSBTYWFzU2VydmljZSBTZXR0aW5nU2VydmljZSBUcmF2ZWxsZXJTZXJ2aWNlIExvY2F0aW9uU2VydmljZSBDb250cmFjdFNlcnZpY2UgQ1JNU2VydmljZSBUYWdTZXJ2aWNlIFJlZnVuZFNlcnZpY2UgRXhwb3J0VmFsaWRhdGlvblNlcnZpY2UgRmluYW5jZVNlcnZpY2UgUmVwb3J0U2VydmljZSBGaWxlU2VydmljZSBTU1JTZXJ2aWNlIiwianRpIjoiZmE4YTRkZjMtOGY4OC00YTE4LTlkNzMtZGIyNmU2ZTBiMTNmIiwic3ViIjoiNDNlNjg3OGMtZGNlYi1mZTlhLWZkOTUtM2ExYjc2ZGRmZjU0IiwiUkxTX09yZ2FuaXphdGlvbklkIjoieW91ci1vcmdhbml6YXRpb24taWQiLCJzZXNzaW9uX2lkIjoiNDdiZjMyNmItZmIzOS00Njk2LTk3ZDQtZDI5ZmMwOTI1YWIwIiwidW5pcXVlX25hbWUiOiJhZG1pbiIsIm9pX3Byc3QiOiJXZWJHYXRld2F5X1N3YWdnZXIiLCJvaV9hdV9pZCI6IjEzNGZhN2M4LTQwMDUtOTQzMi0wZDI4LTNhMWI3NmY4NTc2OCIsInByZWZlcnJlZF91c2VybmFtZSI6ImFkbWluIiwiZ2l2ZW5fbmFtZSI6ImFkbWluIiwicm9sZSI6ImFkbWluIiwiZW1haWwiOiJhZG1pbkBhYnAuaW8iLCJlbWFpbF92ZXJpZmllZCI6IkZhbHNlIiwicGhvbmVfbnVtYmVyX3ZlcmlmaWVkIjoiRmFsc2UiLCJjbGllbnRfaWQiOiJXZWJHYXRld2F5X1N3YWdnZXIiLCJvaV90a25faWQiOiJkNzhjYjMyZS01OTMzLTg4NzMtNDA2Ni0zYTFiOTVmZGM2M2YifQ.OA-zR0hqsSxycGjnmcRYq73vVcgyeytmIKh2hhIM1qLIbfvHRMYNY5lKywkO98jg-Tx5fL0B8UyU4ZyzLNgkhGcAnDoSyBSMiRIKwaVBUiQkbbMvuDkXNHMA6GjQPHjkf4uROZknj-zHtCDrhB6GLUlHaipsOV1nEOouzeRiujx-YgaexR2Aovr32kzQ9jsA7N-16mOtY1ehGVbcCtA2AvEq02aj8NdyiVY-sOYAdzoks-mnRUNjSOFkWOkl80b8qn34vs9tKkHp6pHEUsEqYukrd7k87dle_zV1t3BqQ-hKZeU4fL-SqwzG7jaIsRcd-6Ta8hisdp3X8d52CFODEw
where the token decodes to:
header:
{
"alg": "RS256",
"kid": "4C8A2ECED6FE79F476C9479D50583106DAEB2674",
"x5t": "TIouztb-efR2yUedUFgxBtrrJnQ",
"typ": "at+jwt"
}
payload:
{
"iss": "http://localhost:44332/",
"exp": 1754561764,
"iat": 1754558164,
"aud": [
"AccountService",
"IdentityService",
"AdministrationService",
"SaasService",
"SettingService",
"TravellerService",
"LocationService",
"ContractService",
"CRMService",
"TagService",
"ExportValidationService",
"RefundService",
"FinanceService",
"ReportService",
"FileService",
"SSRService"
],
"scope": "AdministrationService AccountService IdentityService SaasService SettingService TravellerService LocationService ContractService CRMService TagService RefundService ExportValidationService FinanceService ReportService FileService SSRService",
"jti": "fa8a4df3-8f88-4a18-9d73-db26e6e0b13f",
"sub": "43e6878c-dceb-fe9a-fd95-3a1b76ddff54",
"RLS_OrganizationId": "your-organization-id",
"session_id": "47bf326b-fb39-4696-97d4-d29fc0925ab0",
"unique_name": "admin",
"oi_prst": "WebGateway_Swagger",
"oi_au_id": "134fa7c8-4005-9432-0d28-3a1b76f85768",
"preferred_username": "admin",
"given_name": "admin",
"role": "admin",
"email": "admin@abp.io",
"email_verified": "False",
"phone_number_verified": "False",
"client_id": "WebGateway_Swagger",
"oi_tkn_id": "d78cb32e-5933-8873-4066-3a1b95fdc63f"
}
My FirstService is TagService and my SecondService is TravellerService
Hi,
Adding mentioned UserName or UserPassword did not affect the result. I'm still getting the same claims.
yes, the following is my IdentityClients config for local development
...
"IdentityClients": {
...
"SecondService": {
"GrantType": "client_credentials",
"ClientId": "MyApp_FirstService",
"ClientSecret": "1q2w3e*",
"Authority": "http://localhost:44332",
"Scope": "SecondService",
"RequireHttps": false
},
...
},
...
but I do not pass UserName or UserPassword. should I be passing the host admin credentials?
MyApp/apps/auth-server/src/MyApp.AuthServer/OpenIddict/RlsOrganizationClaimsPrincipalContributor.cs
using System;
using System.Linq;
using System.Security.Principal;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Security.Claims;
namespace MyApp.AuthServer.OpenIddict;
public class RlsOrganizationClaimsPrincipalContributor : IAbpClaimsPrincipalContributor, ITransientDependency
{
public ILogger<RlsOrganizationClaimsPrincipalContributor> Logger { get; set; }
public RlsOrganizationClaimsPrincipalContributor(ILogger<RlsOrganizationClaimsPrincipalContributor> logger)
{
Logger = logger;
}
public async Task ContributeAsync(AbpClaimsPrincipalContributorContext context)
{
var identities = context.ClaimsPrincipal.Identities.ToList();
var identity = identities[0];
if (identity == null)
{
Logger.LogWarning("No identity found in the ClaimsPrincipal.");
return;
}
var userId = identity?.FindUserId();
if (userId.HasValue)
{
// Retrieve your custom value (e.g., from a service or database)
var organizationId = await GetOrganizationIdAsync(userId.Value);
if (organizationId != null)
{
identity!.AddClaim(new("RLS_OrganizationId", organizationId));
}
else
{
Logger.LogWarning("Organization ID could not be retrieved for user ID: {UserId}", userId.Value);
}
}
else
{
Logger.LogWarning("User ID not found in the identity.");
}
var ids = context.ClaimsPrincipal.Identities.ToList();
if (ids.Count > 1)
{
Logger.LogWarning("Multiple identities found in the ClaimsPrincipal. Only the first identity will be modified.");
}
}
private Task<string> GetOrganizationIdAsync(Guid userId)
{
// Implement your logic to get the organization ID
return Task.FromResult("your-organization-id");
}
}
The code mentioned about AbpClaimsServiceOptions was not added though, as I couldnt find a clear place where it has the dependency
If you are using OpenIddict or IdentityServer, ensure your custom claim is included in the requested claims:
Configure<AbpClaimsServiceOptions>(options => { options.RequestedClaims.Add("RLS_OrganizationId"); });
[maliming] said: hi
You need to add this
ClaimsPrincipalContributorto AuthServe/Account project
Hi,
I've moved the contributor to AuthServer and now it is being invoked, and the added claim can be seen in the claims in FirstService before the integration service call is invoked, but when I check for SecondService's claims in the method of integration service by using CurrentUser.GetAllClaims(), I still get the same 8 claims
{iss: http://localhost:44332/}
{exp: 1754492934}
{iat: 1754489334}
{aud: SecondService}
{scope: SecondService}
{jti: 48612979-acb1-4c3c-b5eb-cd7d470cae15}
{oi_prst: MyApp_FirstService}
{client_id: MyApp_FirstService}
{oi_tkn_id: 48ffe50b-e1e0-3fe8-ea73-3a1b91e3814e}
[AI-Bot] said: To customize the claims sent during integration service calls in an ABP microservice solution, you can override the claims generation logic by implementing a custom IAbpClaimsPrincipalContributor. This allows you to add custom claims (such as 'RLS_OrganizationId') to the ClaimsPrincipal, which can then be accessed by downstream services.
Here’s how you can achieve this:
- Implement a custom IAbpClaimsPrincipalContributor:
public class RlsOrganizationClaimsPrincipalContributor : IAbpClaimsPrincipalContributor, ITransientDependency { public async Task ContributeAsync(AbpClaimsPrincipalContributorContext context) { var identity = context.ClaimsPrincipal.Identities.FirstOrDefault(); var userId = identity?.FindUserId(); if (userId.HasValue) { // Retrieve your custom value (e.g., from a service or database) var organizationId = await GetOrganizationIdAsync(userId.Value); if (organizationId != null) { identity.AddClaim(new Claim("RLS_OrganizationId", organizationId)); } } } private Task<string> GetOrganizationIdAsync(Guid userId) { // Implement your logic to get the organization ID return Task.FromResult("your-organization-id"); } }
- Register your contributor in the module:
[DependsOn(typeof(AbpAuthorizationModule))] public class YourModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { Configure<AbpClaimsPrincipalFactoryOptions>(options => { options.Contributors.Add<RlsOrganizationClaimsPrincipalContributor>(); }); } }
- If you are using OpenIddict or IdentityServer, ensure your custom claim is included in the requested claims:
Configure<AbpClaimsServiceOptions>(options => { options.RequestedClaims.Add("RLS_OrganizationId"); });
For integration services, ensure that your custom claims are included in the ClaimsPrincipal when making remote calls. The integration service infrastructure will use the current ClaimsPrincipal, so your custom claims will be forwarded if they are present.
On the receiving microservice, you can access the custom claim via ICurrentUser or directly from the ClaimsPrincipal.
This approach ensures your custom claims are available in both local and remote service calls, supporting your row-level security requirements.
Sources:
- https://abp.io/docs/latest/framework/fundamentals/authorization
- https://abp.io/docs/latest/framework/api-development/integration-services
- https://abp.io/docs/latest/Modules/OpenIddict#updating-claims-in-access_token-and-id_token
- https://abp.io/support/questions/6765/CurrentTenant-across-MicroService
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.
Hi,
I've created RlsOrganizationClaimsPrincipalContributor in src/MyApp.FirstService.Application/OpenIddict/RlsOrganizationClaimsPrincipalContributor.cs and included it into the FirstServiceApplicationModule and FirstServiceHttpApiHostModule, but it is not being invoked.