Hooks not firing & rules not working

I’m trying to add a scope to the token, but it appears that my hook is not firing when my user logs in.

Hook code:

module.exports = function(client, scope, audience, context, cb) {
  var access_token = {};
  access_token.scope = scope;


  cb(null, access_token);

I should get a token with the above scope encoded into it, but the token has no scopes.

Note that when I run it in the editor, the return shows that the scope is added.

Because that wasn’t working, I tried creating a rule, but that’s not working either. It fires, but I don’t get an identity token when the rule is active.

function (user, context, callback) {
  if (context.accessToken.scope === undefined) {
    context.accessToken.scope = [];
  callback(null, user, context);

When I run this in the editor, I get a response that shows the scope is added to the accessToken property.

In both cases, I’m using this WPF sample to log in.

Hi Greg. Hooks don’t run when a user logs in (see here for the events to which you can associate a hook).

As for the rule, you are on the right track, that code should work. Are you checking the access_token or the id_token in the result? You mention that “you don’t get an identity token”, but the scopes apply to the Access Token instead.

  • Credentials Exchange: change the scopes and add custom claims to the tokens issued by the Auth0 API’s POST /oauth/token endpoint

I read this as, “I can use the hook to edit the scopes before the token is generated whenever someone asks for a token.” When someone logs in, they’re asking for a token, so I would expect this to fire.

I’ve updated my rule to use context.idToken instead, and while I now get an identity token, it doesn’t contain my scope.

I get this:

id_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ik9EQTFORVZDT1RjNU9EYzBRemxGT1RBeVJETXdNRGd4TjBWRk56QkJSa0UwT1RnelFqYzFOZyJ9.eyJuaWNrbmFtZSI6ImFkbWluIiwibmFtZSI6ImFkbWluQGRlZmF1bHQtYXBwLmNvbSIsInBpY3R1cmUiOiJodHRwczovL3MuZ3JhdmF0YXIuY29tL2F2YXRhci9jMjc1NGYxNGI3MjZjYmZhMmJkNWZiMDkxMzY4ZjMwZj9zPTQ4MCZyPXBnJmQ9aHR0cHMlM0ElMkYlMkZjZG4uYXV0aDAuY29tJTJGYXZhdGFycyUyRmFkLnBuZyIsInVwZGF0ZWRfYXQiOiIyMDE5LTA1LTI3VDAwOjA3OjE0LjY0N1oiLCJpc3MiOiJodHRwczovL2Rldi1nc2QtcHVzaHBheS5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NWNlMzI5ZDRiMDI2YmMxMGY2OWE1MWVhIiwiYXVkIjoiLXZkb252NlFDRTY1NGZFeGJSdFUtTEVtLVY5T0RidXkiLCJpYXQiOjE1NTkwODQ4NjcsImV4cCI6MTU1OTEyMDg2Nywibm9uY2UiOiIxYTg1MGZkOWExYWZhZmIxOGYwYjUyYTlhYTMxM2Q4ZCJ9.TLZSH5yl8SKu--x0UKtKH3gdIEFkyKIBGo5-WpbAJ_l_YRhyeVVEG3NQY3Zkuhv7LQzAmd-svZV3T53lrHUEXfJmYQASK7n2EE2_dOEtG0gFfNaxjoY13-8GNKh_NJ3kUWW1c3Ge5OaGPz2eibwoR9tW7VpSPWCxrHGZcdW1y3gL-yx95yI7uc89oG71a3A_VKxQBzBgjBEX4bf26--Vfs-D3DICz6Y3EduzUIga6bHID5XE7ZCizgtrT8X1asOZrOP4DLbe-dbPVYIDY9EnhQkA_tQUTwVkMR0hzPZE2jADdTr7rdMUlE_eWns6flJMsbxs5ZNwtXTfAsncM88aRg
access_token: jEMyetDUQHRaN-Oh5AFTuWa54E_AA2x-

nickname: admin
name: admin@default-app.com
picture: https://s.gravatar.com/avatar/c2754f14b726cbfa2bd5fb091368f30f?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fad.png
updated_at: "2019-05-27T00:07:14.647Z"
sub: auth0|5ce329d4b026bc10f69a51ea
updated_at: 27/05/2019 12:07:14 AM

The documentation on this is lacking. It says the context has an idToken property, but when I click on the ID Token link, I can’t see what’s available to edit in that field. How would I add a scope as a claim on the JWT that’s returned?

Hi again Greg.

The docs for the hook refer to the Client Credentials Exchange, a flow where an app can directly request a token at the /oauth/token (a machine-to-machine flow) by providing its client id and client secret.In this flow, there’s no user interaction.

As for the missing scope claim in the ID Token: the scope is only available in the Access Token.

The OAuth 2, the Access Token represents a credential that can be used by an application to access a resource (an API). The “scope” claim represents the type or level of access granted for that token.

The ID Token, on the other hand, is a token meant to contain the identity of the user and information about the authentication process. Its target audience is the application itself and it doesn’t carry any scope because it’s not a token used to access a resource.
By default, the ID Token only carry claims defined in the OpenID Connect spec. You can add custom claims to it with additional information about the user, but these claims need to be namespaced (that’s why a scope claim without a namespace is rejected).

This works:

context.idToken["https://yourcompany.com/claims/favorite_color"] = "red";

This doesn’t (because scope is treated as any other claim, and since is not part of the standard OIDC claims is rejected because it’s not namespaced):

context.idToken["scope"] = "something";

I will make a request to the docs team to improve the documentation on the context object to clarify that the context.idToken sub-properties are simply the claims contained in the ID Token (that need to be namespaced if they are not part of the OIDC specification).

Okay… so I’ll go with the Rule, and I’ll use a different approach. I just need to be able to get my ID for the user.

I’ve set up my user to have a myValue property containing a GUID in the app_metadata.

Then I updated the rule to this:

function (user, context, callback) {
  context.idToken.myValue= user.app_metadata.myValue;
  callback(null, user, context);

When I log in, I get an id_token and an access_token, but I don’t see my GUID in either of them.

To add custom claims to either the ID token or the access token, you need to use a namespace, which cannot come from the auth0.com domain. See my previous message (“This works:” / “This doesn’t”).

Okay. I see the difference. What are the requirements for what qualifies as a namespace? I see the examples above and in the linked “custom claims” page using a base url. Are there other options?

Any non-Auth0 HTTP or HTTPS URL can be used as a namespace identifier, and any number of namespaces can be used. The namespace URL does not have to point to an actual resource, it’s only used as an identifier and will not be called by Auth0.
auth0.com , webtask.io and webtask.run are Auth0 domains and therefore cannot be used as a namespace identifier.