Bug: Wrong app_metadata record updated in a multi-tenant architecture


Tenant 1 (Gateway) → Tenant 2

Tenant1 uses Tenant2 database apis to create users in Tenant2, meaning all user records are stored in Tenant2. All actions and rules are created in Tenant1. When trying to update app_metadata in an action in Tenant1, the updated data is stored in the user record in Tenant1 whilst the action is retrieving the user record from Tenant2 (in event.user).

From testing, it seems like app_metadata is always getting read from second level tenant while the updates happen on first level tenant. This results in disconnect between what the action is reading & where it’s writing which breaks the action’s functionality.

Utilizing user_metadata field, however, seems to fix the issue as the user_metadata on tenant lvl 1 and 2 seem to be getting merged on read.

Would really appreciate your input on this!

Hi there @nrzayeva ,

My understanding is as follows:

If tenant2 serves as an Identity Provider in this configuration, users’ profile data from IdP will be synced to Tenant1 records. (Just like when users log into your application via a social Identity Provider like Google, selected Google user profile fields will be synced with the Auth0 tenant.)

Thus, to update the app_metadata in tenant2, my idea would be to call the tenant2’s Management API within the Action script hosted in the tenant1, similar as mentioned here: Update App Meta Data from Post User Registration - #6 by stephanie.chamblee

What do you think?

1 Like

Hey @marcelina.barycka! Thanks for your reply! :slight_smile:

Your suggestion is a good workaround but the management api calls are very expensive. I’m wondering if the api.user.setAppMetadata()function updating the app_metadata at the top-level tenant user record is intended? Like is this the expected behaviour, or could it possibly be a bug?

Hi @nrzayeva ,

Thank you for following up.:slight_smile:

Per design, the api.user.setAppMetadata() function is responsible for updating the relevant user data on the tenant in which the Action runs (it’s not a bug).

Would you like to discuss your use case in more detail?

@marcelina.barycka yeah, to me it seems weird that user_metadata is synced with second level tenant records while app_metadata isn’t. Do you know why do these behave differently or where I could read more about this? :slight_smile:


Hi there @nrzayeva ,

I prepared a longer replay to explain this in detail, so please sit back and enjoy the reading :grin:

user_metadata is something a user potentially has access to and they can update at any time. app_metadata is different and can’t be managed by end users.

If there is any between-tenants syncing in your environment, it is because you / your team have set it up this way. While login, preselected user data from the tenant serving as an IdP will be available in the second tenant’s Action user.event property (and optionally synced). This is the user login context. (Analogous to a user logging in in the context of a Google social connection serving as a primary IdP—a preselected user’s data will be available for the Auth tenant, and if set this way, the Auth0 tenant will be updated with this profile data.)

When you want to write (update) user profile in an external IdP via Actions, things are different. It’s only possible if you manage the external IdP (like in your case, and the Management API calls are here for you). That wouldn’t be possible, for example, in the case of any social connections you do not manage, like social Google.

Another thing is that user_metadata is something a user potentially has access to and can update at any time. app_metadata is different and can’t be managed by end users.

Both Actions’ functions (api.user.setAppMetadata() and api.user.setUserMetadata()) update relevant user data only in the tenant in which the Action runs.
Leveraging the same analogy as above - if a user logs in via the Google social connection IdP, you can still use the same Actions’ functions to update their metadata, but only in the tenant the Action runs in, and you will not update the user’s profile in the Google account this way because you do not manage it.

Reading while the login transaction happens—yes, but updating a user’s profile in the external primary IDP is a separate process.

It’s a good thing that you can write to the external IdP (which is also an Auth0 tenant in your case) from within a different tenant’s Action to update metadata. That would not be possible if the IDP were social Google or any other IDP that you do not manage.

@marcelina.barycka that makes a lot more sense now! thanks a lot for taking the time to explain this :slight_smile: