Assign user role depending on Auth0 app source

Hi dear Auth0 community,

I have some questions regarding role assignment and user_metadata. I searched all the threads and implement the solutions proposed there, but nontheless it seems that my implementation does not behave as expected. I would be really thankful if you can please have a look at my use case described here and please help me with this.

I want to assign a role to a user on onExecutePostUserRegistration depending on the Auth0 application this user signed up with. We have one “Native” Application and one “Single Page Application”, both for different kind of applications. As we have MFA with phone enabled for our applications, on the signup the user needs to enter his phone and verify it. Within Auth0 signup flow provided by the universal login.

I tried the following:

  1. Create an action for the “Pre User Registration” (onExecutePreUserRegistration) where I tried to assign app type as user metadata depending on the source application:
exports.onExecutePreUserRegistration = async (event, api) => {
  // Get source Auth0 application from where this user comes ('Single Page Application' or 'Native Application')
  // ⚠️ 'event.client' is an optional, it can be null 
  const sourceApp = event.client.client_id

  console.log('users source app:', sourceApp)

  if (sourceApp == null) {
    return {
        statusCode: 404,
        body: JSON.stringify({ message: 'We could not determine the originating application here, why?' }),
    };
  }

  // Check 'sourceApp' and see which application it is matching

  if (sourceApp == event.secrets.clientIdApp1) {
    api.user.setUserMetadata("appSource", "app1")
  }

  if (sourceApp == event.secrets.clientIdApp2) {
    api.user.setUserMetadata("appSource", "app2")
  }  
};
  1. I created a “Post User Registration” Action, onExecutePostUserRegistration where I try to assign a role depending on the appSource in user_metadata:
exports.onExecutePostUserRegistration = async (event, api) => {
  // Declare ManagementClient which provide functionality to assign role to user
  const ManagementClient = require('auth0').ManagementClient;
  const management = new ManagementClient({
    domain: event.secrets.domain,
    clientId: event.secrets.clientId,
    clientSecret: event.secrets.clientSecret,
  });

  const userIdParams =  { id : event.user.user_id};
  const app1RoleData = { "roles" : [event.secrets.app1Role]};
  const app2RoleData = { "roles" : [event.secrets.app2Role]};

  try {
    if (event.user.user_metadata.appSource == "app1Role") {
      await management.assignRolestoUser(userIdParams, app1RoleData)
    }

    if (event.user.user_metadata.appSource == "app2Role") {
      await management.assignRolestoUser(userIdParams, app2RoleData)
    }
  } catch (exception) {
    console.log('Error when trying to assign role to user', exception)
    throw {
      statusCode: 500,
      body: JSON.stringify({ error: `An error occurred when trying to assign role to user ${userIdParams}` })
    };
  }
};

Nontheless it seems that this does not work. 1st the assigned user_metadata remains empty when I look at the json of my user:

{
    "created_at": "2023-10-02T09:38:51.413Z",
    "email": "my+user@company.com",
    "email_verified": false,
    "identities": [
        {
            "connection": "MyApp-DB",
            "provider": "auth0",
            "user_id": "xxxxxxxxxx",
            "isSocial": false
        }
    ],
    "name": "my+user@company.com",
    "nickname": "my+user",
    "picture": "https://s.gravatar.com/avatar/xxxxxxxxx.png",
    "updated_at": "2023-10-02T09:39:59.991Z",
    "user_id": "auth0|xxxxxxxxxxx",
    "user_metadata": {},
    "multifactor": [
        "guardian"
    ],
    "multifactor_last_modified": "2023-10-02T09:39:59.991Z",
    "last_ip": "2003:e8:f3b:5c00:80ba:84d8:52de:e199",
    "last_login": "2023-10-02T09:38:51.411Z",
    "logins_count": 1,
    "blocked_for": [],
    "guardian_authenticators": [
        {
            "id": "sms|xxxxxxxx",
            "type": "sms",
            "confirmed": true,
            "name": "XXXXXXXXX3232",
            "created_at": "2023-10-02T09:39:48.000Z",
            "last_auth_at": "2023-10-02T09:39:59.000Z"
        }
    ],
    "passkeys": []
}

Also the role was not assigned to the user:

The reason is here probably because the metadata was already not set as expected, so the conditions in the code posted in “2.” are never given.

Can you please tell me how to assign a role to a user depending on the Auth0 app used? And can you also please tell me how to assign user_metadata? Does it work fe. only on specific Action types? Like fe. only on “Post Login” Actions?

1 Like

Hi @rb090,

Welcome to the Auth0 Community!

Do you users only use Auth0 DB connections? (not google, facebook etc.)

The post registration action probably isn’t the best place to do this, as it’s non-blocking and more geared towards send-and-forget types of requests. I would suggest making the request in a post login action, and do it conditionally based on a flag or something similar. I’d be happy to write an example if you’d like.

Does every user have a role? If so, you can use that to indicate whether or not you need to add it.

Also, user_metadata can be set by the user, which means that the user could potentially choose which role they end up with, is that your desired behavior?

Let me know, thanks!

1 Like

Dear Dan,

thank you so much for getting back to me regarding this issue and also thank you for the warm welcome :slightly_smiling_face:.

Do you users only use Auth0 DB connections? (not google, facebook etc.)

Yes, exactly. ATM we have no social login.

The post registration action probably isn’t the best place to do this, as it’s non-blocking and more geared towards send-and-forget types of requests

Ah okay, thank you for mentioning this. So then this belongs into Post Login Action. I tried my luck and my code looks like this (I use Auth0 3.5.0 dependency because only versions up to 3.5.0 is supported for Node18 Actions):

/**
* Handler that will be called during the execution of a PostLogin flow.
*
* @param {Event} event - Details about the user and the context in which they are logging in.
* @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
*/
exports.onExecutePostLogin = async (event, api) => {
  // Only add user role on users 1st login. If we have a follow up login here after an initial login, do not add user role.
  // @ts-ignore
  if (event.stats.logins_count !== 1) {
    return;
  }

  // Declare ManagementClient which provide functionality to assign role to user
  const ManagementClient = require('auth0').ManagementClient;
  const management = new ManagementClient({
    domain: event.secrets.domain,
    clientId: event.secrets.clientId,
    clientSecret: event.secrets.clientSecret,
  });

  const userIdParams =  { id : event.user.user_id};
  const role1 = { "roles" : [event.secrets.userRole1]};
  const role2 = { "roles" : [event.secrets.userRole2]};

  console.log('Try to assign user role as post login step!')

  try {
    await management.assignRolestoUser(userIdParams, role1)
    // For user type 1 assign role1
    /*if (event.user.user_metadata.appSource == "reactNativeApp") {
      await management.assignRolestoUser(userIdParams, role1)
    }

    // For user type 2 assign role2
    if (event.user.user_metadata.appSource == "singlePageApp") {
      await management.assignRolestoUser(userIdParams, role2)
    }*/
  } catch (exception) {
    console.log('Error when trying to assign role to user', exception)
    throw {
      statusCode: 500,
      body: JSON.stringify({ error: `An error occurred when trying to assign role to user ${userIdParams}` })
    };
  }
};

Does every user have a role?

Yes. Depending on from which app user comes, we need to assign different role.

I am really thankful for a tip on how to distinguish between users app source or sth to make this work :cry:. This is sth I don’t know how to do yet and I am a bit desperate about. I tried as mentioned to introduce a “pre user registration” action to assign an app source like this:

// @ts-nocheck
/**
* Handler that will be called during the execution of a PreUserRegistration flow.
*
* @param {Event} event - Details about the context and user that is attempting to register.
* @param {PreUserRegistrationAPI} api - Interface whose methods can be used to change the behavior of the signup.
*/
exports.onExecutePreUserRegistration = async (event, api) => {
  // Get source Auth0 application from where this user comes ('App1' or 'App2')
  // ⚠️ 'event.client' is an optional, it can be null 
  const sourceApp = event.client.client_id


  if (sourceApp == null) {
    return {
        statusCode: 404,
        body: JSON.stringify({ message: 'We could not determine the originating application here, why?' }),
    };
  }


  // If this is a pre registration for a PatientUser, set metadata 'appType' to 'patientMobileApp' for several post actions
  if (sourceApp == 'xxx-nativeAppClientId-xxx') {
    // never entered
    api.user.setUserMetadata("appSource", "reactNativeApp")
  }

  // If this is a pre registration for a DocUser, set metadata 'appType' to 'docdashWebApp' for several post actions
  if (sourceApp == 'xxx-singlePageAppClientId-xxx') {
    // never entered
    api.user.setUserMetadata("appSource", "singlePageApp")
  }  
};

But the problem is that the event.client.client_id does not match any client id of any of my existing auth0 apps. The output of this object is a complete different string not related to Auth0 app :face_with_spiral_eyes:.

So maybe also this:

Also, user_metadata can be set by the user, which means that the user could potentially choose which role they end up with, is that your desired behavior?

Can be the solution. Can you please tell me ho user_metadata can be added here best? From client via SDK? We use React Native SDK in the Native client and React SDK in the single page application.

1 Like

Hi Dan,

an update on this. I found out why my post registration with the event.client.client_id comparison did not work.

This client_id I received in my pre registration action is the default Application that Auth0 uses for activities performed from the Dashboard. I attempted signing up via the Dashboard. This is because event.client only has information about the client with which this transaction was initiated. If I use the Dashboard, then it will be defaulted to the default App :woman_facepalming:.

I tried registration from a client using Auth0 app and there the event.client.client_id containing what I expected it to contain.

So I guess my issue for this thread is solved :slightly_smiling_face:. Thank you so much for your help and support with this. That was very very kind and is highly appreciated.

1 Like

Great! Glad you found a solution.

Yes, if you are initiating the login from the dashboard (via the “Try” button) you will be using a client ID assigned specifically to the dashboard. I’ll mark this solved.

Thanks for following up!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.