Custom claims not added to access_token despite Rule

I am trying to include app_metadata in my access token using a Rule for my OIDC-compliant client. Whatever I try (including adding a test string to the access token), the access token returned by my app (Angular) when decoded using jwt.io (and also when examined at my REST backend) only contains the following:

{
  "iss": "https://xxxxxxxxxxxx.auth0.com/",
  "sub": "auth0|xxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "aud": 
    "https://xxxxxxxxxxxx.xxxxxxxxxxxx.com",
    "https://xxxxxxxxxxxx.auth0.com/userinfo"
  ],
  "iat": 1518267898,
  "exp": 1518354298,
  "azp": "KQi1KzWkL4BjTL8Ql3aFhVc8TcV2S-Xj",
  "scope": "openid profile email"
}

My Rules looks like this and debugging it has confirmed that my console.logs are being hit:

function (user, context, callback) {
  console.log('in Load User Metadata rule' + user);  
  var namespace = 'https://stratelogics.auth0.com/';
  context.idToken[namespace + 'user_metadata'] = user.user_metadata;
    console.log('added user_metadata to idToken'); 
  console.log('adding test data to accessToken...'); 
  context.accessToken[namespace + 'thisisatest'] = 'this_is_the_test_value';                    
  console.log('added test data to accessToken.'); 
  console.log('adding sms_userid from app_metadata to accessToken...');
  context.accessToken[namespace + 'sms_userid'] = user.app_metadata.sms_userid;
  console.log('added sms_userid from app_metadata to accessToken.');
   callback(null, user, context);
}
2 Likes

I see that youā€™re using an auth0.com domain as the namespace for your custom claims. As stated in the documentation: auth0.com, webtask.io and webtask.run are Auth0 domains and therefore cannot be used as a namespace identifier.

Any non-Auth0 HTTP or HTTPS URL can be
used as a namespace identifier, and
any number of namespaces can be used.
Given your tenant name, you can use something like var namespace = 'https://stratelogics.com/'; as a valid namepace.

4 Likes

@ricardo.batista: I see that youā€™re using an auth0.com domain as the namespace for your custom claims. As stated in the documentation: auth0.com, webtask.io and webtask.run are Auth0 domains and therefore cannot be used as a namespace identifier.
Thank you. I changed my namespace to https://eplsms.stratelogics.com and, still, the data I am looking for is not included in the access token. Hereā€™s the rule:

function (user, context, callback) {
var namespace = ā€˜https://eplsms.stratelogics.com/ā€™;
context.idToken[namespace + ā€˜user_metadataā€™] = user.user_metadata;
context.accessToken[namespace + ā€˜sms_useridā€™] = user.app_metadata.sms_userid;
//context.accessToken[namespace + ā€˜app_metadataā€™] = user.app_metadata;
//context.accessToken[namespace + ā€˜user_metadataā€™] = user.user_metadata;
callback(null, user, context);
}

But the access token payload looks exactly as before.

2 Likes

Did you ever find a solution to this? Iā€™m experiencing the same issue with my app, even though I followed the guide (SPA + API) to the letter. Iā€™ve been struggling with this for the last day with no idea how to proceed. Iā€™m using the live logging with logging statements in my rules and see that the custom claim has been added to the context.accessToken, but when I inspect the token it is missing the claims.

2 Likes

:wave: @tbutman are you still experiencing issues with custom claims? Could you maybe share your Rule here? And are you referring to this guide Single-Page Applications (SPA) with API ?

1 Like

I have this Issue Kim, Please save my day

:wave: @pathmanshakir Rules are triggered once a user authenticates successfully. Is the user signing in first and then you are calling the userinfo endpoint?

1 Like

Hi @kimcodes,

Does it mean that when I perform a request to /oauth/token using Postman, the Rules are not triggered?

Thanks

1 Like

Just to give you more context:

Iā€™m peforming a POST request to /oauth/token via Postman with the following params:
grant_type:client_credentials
client_id: {client_id}
client_secret: {client_secret}
audience: {api_audience} // get this on API > Settings > Identifier

Then I get the access_token and when I inspect using jwt.io I only see the following info:

{
  "iss": ...
  "sub": ...
  "aud": ...
  "iat": ...
  "exp": ...
  "azp": ...
  "scope": ... 
  "gty": ...
}

But I do have a rule to add email and user_id to the access token:

function (user, context, callback) {
  const namespace = 'https://carolpettirossi.com/';
  context.accessToken[namespace + 'email'] = user.email;
  context.accessToken[namespace + 'user_id'] = user.user_id;
  callback(null, user, context);
}
1 Like

I have exactly this issue, my namespace is good, the rule is almost identical to yours, but nothing gets added to the access token. Did you manage to find a solution to this?

2 Likes

Hey, I have the same issue when using context.accessToken, but it seems to work when using context.idToken.

Still trying to find out what to do as wellā€¦

2 Likes

Iā€™m also having an issue as Iā€™m not able to add the custom claims to the access token. It would be interesting to hear if anyone has a solution to adding rules with custom claims to the /token endpoint with an example. Iā€™m facing the same problem.

Looking around I found one discussion that suggested hooks like this instead for the token/ endpoint:
See: Auth0 Hooks
And: How do I get a rule to run when a client (not user) logs in?

And this discussion may implicitly suggest that indeed, it only works to add custom claims to id tokens with rules:

Can someone clarify if hooks are the solution and why? The explanation would help a lot of us.

1 Like

Hey, setting either the scope or a set of custom claims does not work for access tokens. I think I tried every single approach including the two from the rules samples:

  1. Rule Examples
  2. Rule Examples

I tested it both through the ā€œtry itā€ rule button, where the access token is augmented and when logging in and deciphering JWT.

@ricardo.batista could you take a look at it? Iā€™m pinging you as youā€™re the Auth0 employee in this thread and maybe you have some way for testing it internally.

2 Likes

Cześć Szymon!

Recently we have some community developers reporting problems with running their rules. Iā€™m not into the progress of things in that thread but you can find that one helpful:

Cześć :smile: Thx for chiming in. Iā€™ll be watching the thread that you mentioned.

Keep on rockinā€™
Cheers!

1 Like

No worries thanks :slight_smile:

Iā€™m having the same problem with context.accessToken, though does work with context.idToken. But just to double-check (and to help anyone searching at home) you need to include your custom claim URLs in your scope. For instance, if your rule is:

function (user, context, callback) {
  context.idToken['https://carolpettirossi.com/email'] = user.email;
  callback(null, user, context);
}

You would need to add the claim (https://carolpettirossi.com/email) to your scope:

  auth0 = new auth0.WebAuth({
    domain: AUTH_CONFIG.domain,
    clientID: AUTH_CONFIG.clientId,
    redirectUri: AUTH_CONFIG.callbackUrl,
    responseType: 'token id_token',
    scope: 'openid name profile picture https://carolpettirossi.com/email',
  });
4 Likes

That is correct indeed!

For anyone else who ends up here - it appears that Rules are not run for Client Credentials Flow (used by M2M applications hitting the /oauth/token endpoint). According to an Auth0 support personnel:

Actually Client Credentials grant requests do not trigger Auth0 Rules pipeline because they are not considered user logins. They should be used only for Machine-to-Machine API calls.

In order to modify the Access Token scopes or add your own custom claims you can utilize the Client Credentials Exchange Hook: Customize Tokens Using Hooks with Client Credentials Flow

Using Hooks resolved the problem for me, hopefully it helps others out as well.

5 Likes

Thanks a lot @owen for sharing it with the rest of community!