How to check if M2M token vs user token

I have some doubt on how to know if a jwt is an M2M token or if it is a user token. A bit of context:

  • I have a nextjs app using the auth0-nextjs sdk (cookies based), the app has an endpoint that work as proxy to my api, everytime I send a request to this endpoint I get the access_token from the session and I send it to my api.
  • In the Auth0 rules I need to send a request to my api, so I create an access_token with client_credentials grant and I attach it to the reqeust.
    Everything works fine, my doubt is how can I understand if the token is an M2M token or a token created by the user login, the M2M token should be able to the everything in the app while the user token has some restriction. The audience of the 2 token should be the same (I assume) as they are token for the same service. Do I need to use scopes (so the permissions in the api setting page)? Usually is a good practice to have permission like entity:action but in this case I don’t need a granular system I just need to know if the request is coming from a safe place (auth0 rules) and let the token access to everything…

Hi @francesco.venica,

Yes, I believe it’d fall more in line with best practices to handle this by specifying different scopes for users vs. the rule.

Related docs:

Hello @stephanie.chamblee thanks for the feedback, one last question, adding permissions like entity:read/entity:write/entity:delete in the jwt will create a huge jwt because there are a lot of different entities, do you think adding a role claim instead of a scope permission is a bad practice? maybe using a more granular permission in the local db instead of in auth0?

many thanks

You can add the role to the Access Token as a custom claim. Here is an example of that in our docs: Sample Use Cases: Rules with Authorization

This will work for users. However, for the machine-to-machine exchange (the rule calling your API), you won’t be able to add the role since roles are only assigned to users, not non-interactive clients.

You can however use the Client Credentials Exchange hook to modify the Access Token that your API receives. You could add a custom claim that indicates that it is the rule:

1 Like

Hello @stephanie.chamblee,
thanks for the answer, one last question, using the hooks means that I’m adding the same role every time someone create a token using clients_credential right? this means if I need to request a token from another service (that could be less trustable then a rule) that need another set of permission I’m not able to assign those permissions…correct?
I can’t have a token with a role admin (full access) if requested from rules, and a token with role editor (with restricted access) if requested from service (A)

many thanks

That’s right, however, you can add the client name as a custom claim in the Access Token or you can alter the scope based on which client it is, for example:

module.exports = function(client, scope, audience, context, cb) {
    // Claims to be added
    var access_token = {};

    var clientName =;

    // New claim to add to the token
    access_token[''] = clientName;

    if (clientName === 'SomeClient') {

    // Callback to indicate completion and to return new claim
    cb(null, access_token);