Injecting custom claims in the ID token through a rule has no effect

I’ve created a custom rule in order to inject custom claims in the identity token, but it doesn’t work and I’ve no idea why…

This is the code that is use for the rule. When I take a look at the log I can see that “id” and “role” are printed. The only problem is that those two values are not added to the identity token.

function (user, context, callback) {
  
  var namespace = 'https://claims.myapp.com/';
  
  if (user.app_metadata !== undefined) {
    context.idToken[namespace + 'role'] = user.app_metadata.role;
    context.idToken[namespace + 'id'] = user.app_metadata.id;
    
    console.log(user.app_metadata.role);
    console.log(user.app_metadata.id);
  }

  callback(null, user, context);
}

Any idea of what’s going on?

1 Like

Adding custom claims to the ID tokens using the context.idToken method implies that you’re using OIDC conformant authentication. For further reference information on this check the introduction to OIDC docs and this section of the adoption guide to see if this mode of authentication is being used.

Given that your rule is correct from a code perspective it’s highly likely that you’re performing authentication through a legacy endpoint that does not support this; for example, if you’re calling /oauth/ro that rule will have no effect. The alternative for /oauth/ro in terms of OIDC conformant authentication would be for you to use /oauth/token.

If you’re using an SDK then switching to OIDC conformant will depend on the SDK in question. If it’s a browser one, you can quickly check which endpoints are being actually called by checking the browser tools.

Can you be a bit more specific about how to do this? I suspect that’s what’s going on for me, but I’m “just following the instructions”.

Specifically, I find that when using Auth0.js’s authorize() flow (v8), user.app_metadata is undefined by the time a rule like the one above is called.

The user.app_metadata when it exists should be available in rules no matter how authentication started so the problem you describe is likely unrelated to the authentication method being used.

I have similar situation with accessToken.

Rule is very simple:

function (user, context, callback) {
  context.accessToken'http://XXX.auth0.com/email'] = user.email;
  console.log(context.accessToken);
  console.log(user.email);
  callback(null, user, context);
}

And if I try this rule, I get this :

{ 'http://XX.auth0.com/email': 'jdoe@foobar.com' }
jdoe@foobar.com
The profile is: 
{
  "name": "jdoe@foobar.com",
  "email": "jdoe@foobar.com",
  "nickname": "jdoe",
  "picture": "http://foobar.com/pictures/jdoe.png",
  "user_id": "auth0|0123456789",
  "identities": 
    {
      "provider": "auth0",
      "user_id": "0123456789",
      "connection": "Username-Password-Connection",
      "isSocial": false
    }
  ]
}
The rules context is: 
{
  "clientID": "123456789",
  "clientName": "MyWebApp",
  "connection": "MyDbConn",
  "connectionStrategy": "auth0",
  "protocol": "oidc-basic-profile",
  "request": {
    "query": {
      "scope": "openid"
    },
    "body": {},
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36",
    "ip": "X.X.X.X",
    "geoip": {
      "country_code": "AR",
      "country_code3": "ARG",
      "country_name": "Argentina",
      "region": "08",
      "city": "Federal",
      "postal_code": "3180",
      "latitude": -30.954599380493164,
      "longitude": -58.78329849243164,
      "continent_code": "SA",
      "time_zone": "America/Argentina/Buenos_Aires"
    }
  },
  "samlConfiguration": {},
  "stats": {
    "loginsCount": 5
  },
  "accessToken": {
    "http://XXX.auth0.com/email": "jdoe@foobar.com"
  },
  "idToken": {}
}

But “http://XXX.auth0.com/email” is not in the accessToken returned in the response.

Do you have any idea? @jmangelo

Answering my own question above.

It seems XXX.auth0.com is invalid for a domain. As I changed the accessToken key from http://XXX.auth0.com/email to http://$my_random_domain/email, it started working!

1 Like

This recently came up in another ticket so I’m posting it here to help others who may come across this thread with similar issues.

The reason changing the domain worked above is because Auth0 reserves some domains, auth0.com, webtask.io and webtask.run, if any of these are used for a namespace they will be ignored. This is documented here: