Converting Rule to Action

How do you convert the legacy rule called “Move user metadata attributes to profile root attributes” into an Action? The only example I could find was this, but it does not set the user profile value.

exports.onExecutePostLogin = async (event, api) => {
api.user.setUserMetadata(“given_name”, “John”);
};

Hey there @bbarnell welcome to the community!

We unfortunately don’t have a pre-existing example of the same functionality in an Action, but I was able to just test this code in my own environment and it seems to be functioning as expected:

const { ManagementClient } = require('auth0');

exports.onExecutePostLogin = async (event, api) => {
  const fieldMapping = {
    family_name: 'family_name',
    given_name: 'given_name',
    name: 'name',
    nickname: 'nickname',
    picture: 'picture'
  };

  if (needMigration(event.user)) {
    const management = new ManagementClient({
        domain: event.secrets.domain,
        clientId: event.secrets.clientID,
        clientSecret: event.secrets.clientSecret,
    });

    try {
      const updatedUser = await management.updateUser(
        { id: event.user.user_id },
        generateUserPayload(event.user)
      );
      updateActionUser(event.user, updatedUser);
    } catch (err) {
      console.error(err);
      throw new Error('Failed to migrate user attributes.');
    }
  }

  function needMigration(user) {
    if (user.user_metadata) {
      for (const key in fieldMapping) {
        if (typeof user.user_metadata[fieldMapping[key]] === 'string') {
          return true;
        }
      }
    }
    return false;
  }

  function generateUserPayload(user) {
    const payload = { user_metadata: {} };
    const userMetadata = user.user_metadata;

    for (const key in fieldMapping) {
      generateUserPayloadField(userMetadata, payload, key, fieldMapping[key]);
    }

    return payload;
  }

  function updateActionUser(user, updatedUser) {
    for (const key in fieldMapping) {
      if (typeof user.user_metadata[fieldMapping[key]] === 'string') {
        user[key] = updatedUser[key];
        delete user.user_metadata[fieldMapping[key]];
      }
    }
  }

  function generateUserPayloadField(userMetadata, payload, rootField, metadataField) {
    if (typeof userMetadata[metadataField] === 'string') {
      payload[rootField] = userMetadata[metadataField];
      payload.user_metadata[metadataField] = null;
    }
  }
};

I attempted to mirror the Rule code as closely as possible - I will note that it might be worth looking into caching the Management API access token as well:

Hope this helps!

I was unable to get this code to work, so I tried to simplify it and now I get this error message when I run the script in the editor window. What am I doing wrong?

unauthorized_client: {“error”:“unauthorized_client”,“error_description”:“Grant type ‘client_credentials’ not allowed for the client.”,“error_uri”:“Application Grant Types”}
at /data/layers/

Here is my test code:

const { ManagementClient } = require(‘auth0’);

exports.onExecutePostLogin = async (event, api) => {

  const management = new ManagementClient({
     domain: event.secrets.domain,
     clientId: event.secrets.clientID,
     clientSecret: event.secrets.clientSecret,
  });

  const user = event.user;
  const user_id = user.user_id;

  user.user_metadata.given_name = "John Doe";
  const given_name = user.user_metadata.given_name;

  console.log("** user_id: " + user_id);
  console.log("** given_name: " + given_name);
  console.log("** user object", user);

  const updateUserData = {given_name: given_name};
  
  try {
     const updatedUser = await management.updateUser(
        { id: user_id },
        updateUserData
     );

     console.log("** Updated user", updatedUser);
     
  } catch (err) {
     console.error(err);
     throw new Error('Failed to migrate user attributes.');
  }

};

This most likely has to do with the application you are using to instantiate the ManagementClient - This should be an M2M app and you should see “Client Credentials” enabled if you go to application settings → advanced settings → grant types.

The application also needs to be authorized by the Management API - You can do this by navigating to applications → APIs → Management API → machine to machine applications.

This is a Mobile Single Page application where I am trying to convert the rule: legacy rule called “Move user metadata attributes to profile root attributes” into an Action before it expires next year and no longer works. What is the best approach for this? I am getting nowhere coding actions.

1 Like

Hey @bbarnell !

The code I shared previously works in my own environment, so it should work in yours. Are you able to go into a bit more detail as to why exactly the code wasn’t working for you? The more details you can share the better.

Please close this ticket. I found a workaround for this issue.

1 Like