How to get scopes in access token

Hi, we are migrating from Rules to Actions.
I understand we can add/remove scope by api.accessToken.addScope() and api.accessToken.removeScope().

Is there is a way to list existing scopes in accessToken? We need to remove scope on Post Login but need to know what’s already in there.

Hello @andy.cui1 welcome to the community!

You should be able to get these with event.transaction.requested_scopes of the Event object.

console.log(event.transaction.requested_scopes);

Gives me “undefined”

How about:

 if (event.authorization) {
  console.log(event.transaction.requested_scopes);
 }

Same, it still print out undefined

Hmm, that’s odd - Are you able to print out event.transaction? What type of login flow are you using in particular?

event.transaction is { protocol: 'oauth2-password' }
I am making POST request to /oauth/token endpoint with client_id, client_secret, audience, grant_type=http://auth0.com/oauth/grant-type/password-realm, username, password and realm
Not sure what is the name of this type.

Ah, thanks for clarifying!

Because you’re using a password grant type, scopes won’t be accessible in event.transaction.requested_scopes as scope filtering is not done for ROPG grant types. Instead you’ll need to get scopes from the body of the request, something like:

const reqeustedScopesArray = event.request.body.scope?.split(" ")

This is still undefined.

I’d like to provide more context on my use case.
I am migrating Auth0 Rules to Actions. One of the current rule is assigning scopes in accessToken
context.accessToken.scope = ["some-scopes"];
In Actions, there is no assignment, I can only add or remove scopes. So I just add the ones I want to the accessToken
api.accessToken.addScope("a"); apt.accessToken.addScope("b");
But the final access toke contains a lot more than I added in Actions. Seems like some of them are pre-populated into the access token scope.

So I need to clean up before running my api.accessToken.addScope(); But couldn’t find a way to do that.

Gotcha, thanks for clarifying!

Do you know where these scopes are coming from? AFAIK using a password grant and omitting the scopes param in the request results in an access token with no scopes at all. The only way I can access scopes in an Action is if I add them to the request as outlined here.

The scopes are all permissions defined in the API. But I have no idea where they come from. I tried turn off all custom rules and Actions. (just leave the default auth0-authorization-extension rule). But the scopes are still in the access token.

Perhaps they are being added in the authorization extension itself?

It is pretty much the default. I don’t see it adding any scope in it.

function (user, context, callback) {
  var _ = require('lodash');
  var EXTENSION_URL = "OUR_INSTANCE_URL";

  var audience = '';
  audience = audience || (context.request && context.request.query && context.request.query.audience);
  if (audience === 'urn:auth0-authz-api') {
    return callback(new UnauthorizedError('no_end_users'));
  }

  audience = audience || (context.request && context.request.body && context.request.body.audience);
  if (audience === 'urn:auth0-authz-api') {
    return callback(new UnauthorizedError('no_end_users'));
  }

  getPolicy(user, context, function(err, res, data) {
    if (err) {
      console.log('Error from Authorization Extension:', err);
      return callback(new UnauthorizedError('Authorization Extension: ' + err.message));
    }

    if (res.statusCode !== 200) {
      console.log('Error from Authorization Extension:', res.body || res.statusCode);
      return callback(
        new UnauthorizedError('Authorization Extension: ' + ((res.body && (res.body.message || res.body) || res.statusCode)))
      );
    }

    // Update the user object.

    // Store this in the user profile (app_metadata).
    saveToMetadata(user, data.groups, data.roles, data.permissions, function(err) {
      return callback(err, user, context);
    });
  });
  
  // Convert groups to array
  function parseGroups(data) {
    if (typeof data === 'string') {
      // split groups represented as string by spaces and/or comma
      return data.replace(/,/g, ' ').replace(/\s+/g, ' ').split(' ');
    }
    return data;
  }

  // Get the policy for the user.
  function getPolicy(user, context, cb) {
    request.post({
      url: EXTENSION_URL + "/api/users/" + user.user_id + "/policy/" + context.clientID,
      headers: {
        "x-api-key": configuration.AUTHZ_EXT_API_KEY
      },
      json: {
        connectionName: context.connection || user.identities[0].connection,
        groups: parseGroups(user.groups)
      },
      timeout: 5000
    }, cb);
  }

  // Store authorization data in the user profile so we can query it later.
  function saveToMetadata(user, groups, roles, permissions, cb) {
    user.app_metadata = user.app_metadata || {};
    user.app_metadata.authorization = {
      groups: groups,
      roles: roles,
      permissions: permissions
    };

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

Do you mind DMing me the tenant you are testing with as well as an example access token payload decoded at jwt.io?