How do I get an access token to call Management API v2 from a rule?

Many rules need to access Management API v2 to perform duties. It used to be possible to generate a non-expiring token from the Management API v2 documentation page and store it as a configuration value.
Since that option is not available anymore (or, at least, not recommended), what’s the best way to get an access token to Management API v2 from rules?

The rule execution context will behave like any other non-interactive client, having to get an access token using the client credentials grant.

First, you will have to create a non-interactive client and authorize it to access Management API v2. Choose the required scopes, and name it in a meaningful way, like “Management API v2 client for rules”.

Then, configure the following settings for rules:

  • AUTH0_DOMAIN: your Auth0 domain, like contoso.auth0.com.
  • APIV2_CLIENT_ID: the id of the non-interactive client you created
  • APIV2_CLIENT_SECRET: the secret of the non-interactive client

Finally, use a code like this to obtain the token. Notice that this code does some caching, to avoid getting a new access token every time the rule is run:

function (user, context, callback) {
  var getApiv2AccessToken = function(domain, clientId, clientSecret, cb) {
    var cacheKey = clientId + '_token';
    var cachedToken = global[cacheKey];
    if (cachedToken && cachedToken.expirationDate > Date.now()) {
        // token is valid
        return cb(null, cachedToken.accessToken);
    }
    
    // token not present or expired, get a fresh one
    var request = require("request");
    var options = { method: 'POST',
      url: 'https://' + domain + '/oauth/token',
      body:
      { client_id: clientId,
        client_secret: clientSecret,
        audience: 'https://' + domain + '/api/v2/',
        grant_type: 'client_credentials' },
      json: true };

    request(options, function (error, response, body) {
      if (error) {
        console.log('Error getting access token for API v2.', error);
        return cb("Error getting access token: " + error);
      }
      global[cacheKey] = {
        accessToken: body.access_token,
        // 60 seconds safe window time
        expirationDate: Date.now() + (body.expires_in - 60) * 1000
      };
      return cb(null, body.access_token);
    });
  };
  
  // sample usage
  getApiv2AccessToken(
    configuration.AUTH0_DOMAIN, 
    configuration.APIV2_CLIENT_ID, 
    configuration.APIV2_CLIENT_SECRET, 
    function(err, accessToken) {
      if (err) {
        callback(err);
      }
      // now call the API v2 with the accessToken
      ...
      // and continue
      callback(null, user, context);
    });
}
4 Likes

You sir are a life saver