Auth0 Home Blog Docs

User app metadata set in rule is only available in JWT in the next login

bug
jwt
app_metadata

#1

I’m using auth0.js v8.

Steps to reproduce

Step 1

Call authorize() with id_token as requestType to get a JWT and scope openid color.

Step 2

Setup a rule that modifies user.app_metadata

function (user, context, callback) {
  user.app_metadata = user.app_metadata || {};
  user.app_metadata.color = user.app_metadata.color || 'blue';

  auth0.users.updateAppMetadata(user.user_id, user.app_metadata)
    .then(function(){
        callback(null, user, context);
    })
    .catch(function(err){
        callback(err);
    });
}

This is simply the example rule Add persistent attributes to the user with user.app_metadata swapped out with user.user_metadata.

Step 3

Login with any user and console log the JWT

You will see that color is NOT set in the JWT.

You will also see in the Auth0 backend that color is set on the user.

Step 4

Logout

Step 5

Login again with that same user and console log the JWT

You will see that color is now set in the JWT.

You will also see that in the Auth0 backend that color is still set on the user.

Expected behaviour

I expect that the JWT tokens received in step 3 and step 5 are identical.


#2

The automatic inclusion of custom information in the ID token (non-standard OpenID Connect claims for which color would be a good example) is part of what’s now considered the legacy authentications flows; these are still supported, but it’s not likely that the behavior you experienced will change, in particular, because there’s also a workaround. As a side note, in an OIDC compliant flow you would have to explicitly add custom claims to the token so this would end-up being a non-issue.

If you want that the new app_metadata property being added to also be considered when issuing the ID token for the current transaction then you can update your rule logic to something like the following:

function (user, context, callback) {
  user.app_metadata = user.app_metadata || {};

  if (!user.app_metadata.color) {
    var color = "blue";

    user.app_metadata.color = color;

    // set it also at the user level so that is available to be issued
    // in the token for this transaction
    user.color = color;

    auth0.users.updateAppMetadata(user.user_id, user.app_metadata)
      .then(function() { callback(null, user, context); })
      .catch(callback);
  } else {
    callback(null, user, context);
  }
}

The above should get you consistent behavior for the scenario you described.


#3

OK yes, it seems pushing the data onto the user object itself seems to workaround this inconsistency.

Hopefully this behaviour continues to be supported :slight_smile:


#4

OK yes, it seems pushing the data onto the user object itself seems to workaround this inconsistency.

Hopefully this behaviour continues to be supported :slight_smile:


#5