Syncing Auth0 with external identifiers

Guy Avraham
2 min readApr 13, 2021

Recently I managed a mobile app with Auth0 authentication and connected each user to its CRM’s identifier. For me, the connecting field was the phone number (for SMS passwordless connection type).

To get that I used a post-login Rule: Auth0 will call your backend with some fields and get back the external user ID and other relevant metadata, then save the external user id on the Auth0 user metadata.

Later when you want to get this data on the IDToken auth inside your JWT you need another rule to save from the user_metadata into the IDTOKEN.

Create the first rule — use “Add persistent attributes to the user”. You can probably use the code that Auth0 used there as a template.

This is my code for the first rule:

const fetch = require("node-fetch");

function onLoginRule(user, context, callback) {
function isToday(someDate) {
if (!someDate) return false;
if (_.isString(someDate)) someDate = new Date(someDate);

const today = new Date();
return (
someDate.getDate() === today.getDate() &&
someDate.getMonth() === today.getMonth() &&
someDate.getFullYear() === today.getFullYear()
);
}

console.log("*** user", user);

if (user.user_metadata && isToday(user.user_metadata.lastUpdate)) {
console.log("Can use cache");
callback(null, user, context);
return;
} else {
const url = configuration["exist-by-phone-url-prod"];
const key = configuration["exist-by-phone-key-prod"];

const body = {
phoneNumber: user.phone_number,
extended: true,
};
const finalResponse = { user };

console.log("data rule start");

const options = {
method: "post",
body: JSON.stringify(body),
headers: {
"Content-Type": "application/json",
"x-api-key": key,
},
};

console.log("*** url, options", url, options);

return fetch(url, options)
.then((res) => {
if (res.status !== 200) {
throw new Error(`${res.status} httpCode for crm fetch`);
}
return res.json();
})
.then((json) => {
const metadata = {
name: json.name,
lastUpdate: new Date(),
...json,
};
console.log("metadata", metadata);
finalResponse.user.user_metadata = metadata
return auth0.users.updateUserMetadata(user.user_id, metadata);
})
.then((updateUserMetaResponse) => {
console.log("updateUserMetaResponse", updateUserMetaResponse);
callback(null, finalResponse.user, context);
})
.catch(function (err) {
console.log("rule error:", err);
callback(null, user, context);
});
}
}
  1. Here I'm syncing other product-specific data with the CRM so it's not only the external user Id.
  2. If there was a sync today, I don't run it again.
  3. In the rules section, fill configuration keys and values for your URL and secrets.
  4. You can debug this rule inside the rule editor with “Save and Debug”.
  5. You can debug real usage of this rule by installing the “Real-time Webtask Logs” Extension. Just find the Extension menu in the Auth0 dashboard, and try with a real signing to your app.
  6. Now ideally we can see user metadata of users under the “Users” menu.

Create a second rule for having this data with IdToken JWT:

function (user, context, callback) {
if (context.idToken && user.user_metadata) {
const namespace = 'https://crm.yourNamespace.com/';
context.idToken[namespace] = user.user_metadata;
context.idToken[namespace + 'name'] = user.user_metadata.name;
}
console.log('**rule context', context.idToken);
callback(null, user, context);
}
  1. By the docs, data must be saved under a namespace key.

When you log in to your client:

Make sure to pass the parameter of

response_type: 'token id_token'

1. id_token will return a JWT token with the profile as described on the scope.
2. token will return access_token to use with further API calls.

--

--