Attribute mapping, after Sign in with Apple

Hi Auth0 Community,

As you know, Auth0 does not provide a convenient way to map user attributes for social logins. So, we need to write a script for Actions to map them.

On the other hand, some of the social IdP providers, such as Apple, give first_name and last_name attributes, which are incompatible with OIDC Standard attributes (Standard is given_name and family_name).

So I tried to write a script for Pre-User Registration Actions, but the API object does not allow me to change user given_name and family_name attributes.

I also tried Login / Post Login Actions, and it’s the same. API object only has setAppMetadata and setUserMetadata, which are not the correct methods for updating the user’s given_name and family_name attributes.

At this point, what exactly can I do for this very basic but complicated process?

1 Like

Hi @sefer , welcome!

You could consider setting Apple connection as a custom social Identity Provider connection to provide fields mapping.
The place to go would be Auth0 dashboard → Authentication → Social → Create connection → Create Custom.

This article describes it.
While setting this up you would provide fields mapping within the Fetch User Profile script.
The Fetch User Profile script perform a call to the IdP to fetch user profile data.

A sample Fetch User profile script:

If you decide to go with that, you can also find additional support by searching this community for topics like “Fetch user profile script”, “custom social connection”, “Custom IdP” and similar.

I also stay available for follow up questions.

Here is my solution. Your feedback would be appreciated,

exports.onExecutePostLogin = async (event, api) => {
  
  // Exchange first and last name with given and family name if the user comes with Apple
  if (event.connection.strategy === 'apple' && event.user.first_name && event.user.last_name) {
    const token = await getManagementApiToken(event.secrets.M2M_CLIENT_ID, event.secrets.M2M_CLIENT_SECRET, event.secrets.AUTH0_AUD, event.secrets.AUTH0_DOMAIN);
    await updateUserProfile(token, event.user.user_id, event.user.first_name, event.user.last_name, event.secrets.AUTH0_DOMAIN);
  }
};

async function getManagementApiToken(clientId, clientSecret, audience, domain) {
  const response = await fetch(`https://${domain}/oauth/token`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      client_id: clientId,
      client_secret: clientSecret,
      audience: audience,
      grant_type: 'client_credentials'
    })
  });

  const data = await response.json();
  return data.access_token;
}

async function updateUserProfile(token, userId, givenName, familyName, domain) {
  await fetch(`https://${domain}/api/v2/users/${userId}`, {
    method: 'PATCH',
    headers: {
      Authorization: `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      given_name: givenName,
      family_name: familyName,
      first_name: null,
      last_name: null
    })
  });
}
1 Like

Thanks so much for sharing @sefer !

From my side, I would like to also let you know that to interact with the Auth0’s Management API (to update user profile data like given_name or family_name) you could use within this Action our “auth0” library instead of writing your own function.

A simplified code sample form our Github repo (it updates user metadata):

exports.onExecutePostLogin = async (event, api) => {
import { ManagementClient } from 'auth0';

const management = new ManagementClient({
  domain: '{YOUR_TENANT_AND REGION}.auth0.com',
  clientId: '{YOUR_CLIENT_ID}',
  clientSecret: '{YOUR_CLIENT_SECRET}',
});

await management.users.update({ id: '{user id}' }, { user_metadata: { foo: 'bar' } });
}

I’m sharing it in case you would like to compare performance of calling our Management API with a custom function versus using our library.

ref.

1 Like

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