I’d like to set up a rule that adds roles to a user on sign up based on some criteria that centres around their email address). There are lost of posts on the community about this topic and I’ve got a rule that pushes roles into the app_metadata for the user working, but those roles don’t then appear in the Roles section of Auth0:
I’m new to Auth0 so not sure if this new way of managing roles is new and hasn’t made it into the example code or community chat much yet, but I’m struggling to work out to to grant a role defined in that section above to a user, which is different from adding an array of strings to app_metadata. Any guidance would be appreciated.
That roles link takes you to the the new “Authorization Core” feature documented at the link below. Storing role information yourself in metadata is fine, but only for a do-it-yourself solution. There is also the older Authorization Extension, which I believe the newer Authorization Core feature will eventually replace. So there are three options:
DIY - store your own role data in metadata, create rules and / or application logic to implement access control,
Authorization Core - the new RBAC capability in Auth0 which has its own API,
Authorization Extension - “legacy” RBAC capability which also has its own API, but can optionally store role data in metadata.
Okay, so it does seem I have stumbled into a newer feature that’s not widely used yet. I definitely don’t want to use any legacy features if I can help it, and I’m already somewhat committed to the roles and permissions setup of Authorization Core, having set everything up that way already. Is it currently possible to write to the Authorization Core API to set roles for a user in either a Rule or a Hook?
I was wrong about the new Authz Core feature having its own API. Not sure where I got that from. All the Authz Core stuff is part of the Management API under the roles and users endpoints.
I haven’t tried this myself, but you can access the management API directly from a rule:
Perfect, thanks so much @markd. I’ve got this working exactly as I wanted now. Sharing the code below in case it’s useful to anyone else:
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);
});
}