Auth0 Home Blog Docs

Add Auth Core Role on Automatic User Migration

I recently setup a new Auth0 connection database, configured as a “custom database” with automatic migration turned on. This works great – upon initial sign in, it reaches out to my legacy SQL user store and migrates it over with the proper id, password and metadata.

I’m at a loss as to how I can, at the point of migration, assign an Auth Core Role (for RBAC) to the user based on their profile from SQL. I have turned on “Add Permissions in the Access Token” - so the goal is to have the permissions for the assigned roles be populated in the initial access token.

What I’ve tried:

  • Added a roles array under both the app_metadata and user_metadata objects, knowing there was no reason this would work :slight_smile:

  • Creating a rule to read the user’s role out of app_metadata and assign it to the real role system via the Auth0 Management Client. This does add the role, however the permissions do not appear until the subsequent login.

  • Creating a hook to do the same as above, but it doesn’t solve the problem. Not only do the hooks not seem to trigger on the migration event, but the lifecycles don’t match up - either the user doesn’t exist yet (pre-creation) or it happens async outside of the login process.

Any ideas? Anything simple I’m missing that would allow me to pull this off?

Thanks!

Hi @producdevmatt,

This should be possible. Can you DM me your tenant name so I can take a look at the rule you are using?

Thanks
Dan

Thanks for the quick reply, Dan

We ended up taking a different approach in the short term so I deleted my rule :confused: But, we need to make this happen eventually. What I was using is a simplified version of the same code as this other post:

function (user, context, callback) {

  // Roles should only be set to verified users.
  if (!user.email || !user.email_verified) {
return callback(null, user, context);
  }
  
  // short-circuit if the user signed up already or is using a refresh token
  if (context.stats.loginsCount > 1 || context.protocol === 'oauth2-refresh-token') {
return callback(null, user, context);
  }
  
  const getRolesForUser = (user) => {
const roles = [
  'rol_XXXXXXXXXXXX' // default
];
try {
  const emailDomain = user.email.split('@')[1].toLowerCase();
  switch (emailDomain) {
    case 'somedomain.com':
      roles.push('rol_XXXXXXXXXXXX');
      break;
    // More custom rules here
  }
  return roles;
} catch (e) {
  console.error(e);
  return [];
}
  };
  
  const roles = getRolesForUser(user);
  
  // Role management was introduced in 2.17.0.
  // 2.17.1 intermittently returned package not found error.
  // Unspecified version didn't support roles, so must be earlier than 2.17.0
  var ManagementClient = require('auth0@2.17.0').ManagementClient;
  var management = new ManagementClient({
token: auth0.accessToken,
domain: auth0.domain
  });
  
  // Update the user's roles
  management.assignRolestoUser({ id : user.user_id }, { roles: roles }, (err) => {
if (!err) {
  console.log('Roles [' + roles.join(', ') + '] assigned to user [' + user.email + ']');
} else {
  console.error(err);
}
return callback(err, user, context);
  });
  
} 

It does work - the user migration from SQL happens, it properly adds the role, but the “permissions” array does not get populated on the JWT token when “Add Permissions in the Access Token” is turned on.

On the subsquent login, the permissions array is filled as expected.

Any ideas there?

And as sort of a follow-up, would there be any good way to pull this off with role names instead of ids? I suppose you could make an initial call to get all the roles.

Thanks for any help / thoughts!