Adding role to user from hook

I recently wanted to start adding a role and sending a Slack notification when a user signed up. I got that hooked up via rules, but the rules have been running multiple times. Despite the code that controls that being part of Auth0’s sample code, these discussions suggests it’s not going to work right anytime soon:

https://community.auth0.com/t/slack-notification-rule-is-triggering-more-than-once/30844/11

After further digging, I determined that hooks are a newer mechanism to do this kind of stuff, and would likely be more reliable. So I set up a post-user-registration hook and proceeded to migrate my code.

I got the Slack piece moved easily enough, but I’m stuck on the role piece. Here’s the snippet of code I’m using in the old rule:

var headers = {
    'Authorization': 'Bearer ' + auth0.accessToken,
};
const data = {
    "roles": [
        "rol_****"
    ]
};

request.post({
    url: `https://${auth0.domain}/api/v2/users/${user.user_id}/roles`,
    headers: headers,
    json: data
}, (err, response, body) => {
    return callback(new Error("Can not update users with role"));
});

That auth0 object that your rule runner makes available to the rule doesn’t seem to be available in the hook. Is there something else I should use? If not, how do I do this?

After further digging, I determined that hooks are a newer mechanism to do this kind of stuff, and would likely be more reliable.

No, that’s not correct (about reliability). Both Rule and Hooks are reliable in the same way. Hooks and Rules have different extension points (Rules trigger upon a successful authentication, Hooks trigger at user registration (only for database connections)).

Rules can be used for your use case, and the benefit is that you have the auth0 helper object at hand.

Regarding this question:

That auth0 object that your rule runner makes available to the rule doesn’t seem to be available in the hook. Is there something else I should use?

There is no other way (no helper object) in Hooks than making raw Node.js requests.

I got the Slack piece moved easily enough, but I’m stuck on the role piece.

In case you want to continue with Hooks: what in your code sample doesn’t work, where/how does it fail?

1 Like

My code sample works fine in a rule, but it doesn’t work in a hook because the auth0 object isn’t defined, and your message suggests there’s not a good equivalent. That’s super-odd to me (why have that in rules but not hooks?), but if true, does mean I need to manually hit the APIs to add the role.

By hooks being more reliable than rules, I mean for this specific case. The framework of my rule code comes from this official sample code:

It works great – except for the fact that the rule frequently fires multiple times. I’m not exactly sure the conditions that trigger it, but I think it’s when the user creates an account and keeps the window (i.e., session) around after account creation and continues to access it. As you can see from the discussions I linked in my first message, this bug in the sample code has been around for a few years, and there are even Auth0 employees suggesting a rule is the wrong approach, thus my comment about reliability of this approach for this purpose.

That said, if we can figure out how to make the rule properly bail out when the user already exists, that would solve my problem beautifully. Looking at the sample code, the logic that should handle this task is in this snippet from the beginning:

if (context.stats.loginsCount > 1 || context.protocol === 'oauth2-refresh-token') {
	return callback(null, user, context);
}

That seems like solid logic, but there’s plenty in there that could be wrong that I can’t catch without a far more detailed understanding of Auth0’s calling conventions for rules. And it may be completely correct based on how it’s supposed to be called but they’re just not calling it correctly.

why have that in rules but not hooks?

Different development teams/phases. Agree, would be good to have it in both. Might eventually come at some point.

It works great – except for the fact that the rule frequently fires multiple times. […] That said, if we can figure out how to make the rule properly bail out when the user already exists

it doesn’t work in a hook because the auth0 object isn’t defined,

Sorry, I missed the auth0 object in your code line

'Authorization': 'Bearer ' + auth0.accessToken,

Ok, so in this case, you’d need to execute the M2M / Client Credentials Grant manually for first fetch a token for the Auth0 Management API. For this, you’d need to first create a M2M client application, then give it permissions to the Management API, etc. It’s a bit more additional effort than going with a Rule.

Right. If I need to fuss with that and still bumble around with doing the API comms in JS (a language at which I rather suck), it might be better for me to add an endpoint to my application that I can hit from the hook, then do it on the app side. That puts me in PHP land (I’m much better at that!) with Auth0’s easier-to-use SDK, plus the app is already set up for API interactions with Auth0, and my code would be version controlled, easier to debug, etc. Thinking about it, that’s probably the best way to go, but the app wasn’t there yet when I initially set this up, and I guess I was sort of stuck in the mindset of making it work.

That said, I’m still open to using the rule if there’s a way to get it working properly.

It can definitely work with Rules.

I suggest these docs pages if you haven’t read them yet.


Rules run sequentially and are always triggered at successful authentication, regardless of connection type, etc. Inside a rule, you can use if/else statements to only execute certain logic based on i.e. client ID, type of connection a user is coming from, if it’s the user’s first login.

and my code would be version controlled, easier to debug

Note that Auth0 offers extensions for Github, Gitlab, etc. that allows to store Rules in a git repo and deploy it from there. This allows for versioning, etc.

Rules debugging can be done with https://auth0.com/docs/extensions/real-time-webtask-logs