Update the Phone Number of Users with Management API for Custom Database

Overview

This article explains how to update the phone numbers for users with management API with a custom database (DB).

The phone attribute is enabled as an identifier together with the email attribute for the connection.

Sample update user attempt:

curl -L -X PATCH 'https://<TENANT-NAME>.auth0.com/api/v2/users/USER-ID' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Authorization: <Bearer ey..redacted>' \
-d '{"phone_number":"+xxxxxxxxxx"}'

Applies To

  • Custom Databases
  • Import Users to Auth0 Option Disabled

Solution

As a general recommendation, if a custom DB is integrated with Auth0, all the updates to the user profiles should be implemented through Auth0 custom DB scripts.

  • Directly modifying the database and bypassing the Auth0 scripts can lead to several inconsistencies.
  • This knowledge article expands on some common errors that may occur due to bypassing the Auth0 custom DB scripts.
  • Similar errors can also happen with email and username identifier updates, but this article only explains the phone number attribute use case for brevity.

Execution order of the custom DB scripts:

During a user patch operation for the phone number, the Get User script is executed twice, and then the Change Phone Number script is executed. As of 2025 February, the Change Phone Number script is not visible from the Auth0 dashboard but can be updated using the management API. Please look at the example at the end for how to update the script.

1. The first Get User script call helps to check if the user exists.

This call will have the user’s existing phone number. This request must be returned with an existing user profile.

E.g.

function getUser(identifierValue, callback) {
  console.log("identifierValue", identifierValue); // has the user's email, username, or the phone number
  
  //Other codes that fetch the user from external DB are removed for brevity
  
  // The purpose of the first call to Get User script is to extract the user profile from the external DB 
  // to compare it with the existing user profile on Auth0 when the management API was called to patch the identifier.
  // The returned profile should match the user currently stored in Auth0 and return callback(null, profile);
  if (profile) {
   return callback(null, profile);
  else {
    return callback(null);
  }
}

At this step, if the script cannot return the exiting user from the external database, Auth0 throws the following error:

{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "User with old phone_number does not exist in Auth0 database",
  "errorCode": "auth0_idp_error"
}

If, on this call, the user profile is missing the expected old phone number on the legacy DB, this would be considered an inconsistency, and the script would fail.

2. The Get User script is called the second time with the new phone number to patch the user.

This execution is expected to return no user profile.

function getUser(identifierValue, callback) {
  console.log("identifierValue", identifierValue); // has the user's email, username, or the phone number
  
  //Other codes that fetch the user from external DB are removed for brevity

  // On the second execution, the identifierValue is the new phone number we are attempting to set to the user 
  // Auth0 expects there is no other user in the external DB with this phone number hence, we expect the script
  // returns callback(null);
  if (profile) {
   return callback(callback, profile);
  else {
    return callback(null);
  }
}

At this step, if the function unexpectedly returns the profile with a callback(null, profile) call, Auth0 throws the following errors:

If the phone number being updated was already set on the external DB and the script returns it with the phone_number attribute in the profile object, Auth0 throws the following error:

{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "The specified new phone_number already exists",
  "errorCode": "auth0_idp_error"
}

If the phone number being updated is different than the one already set in the external DB and that number is returned with the phone_number attribute in the profile object, Auth0 throws the following error:

{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "returned profile does not contain specified identifying attribute",
  "errorCode": "auth0_idp_error"
}

3. Change phone number is executed next to update the user on the external database if the Get User script executions work as intended.

The change_phone_number script must be implemented to update the external database with the new phone number. If the script is missing, Auth0 will throw the following error. This function has not been documented yet, but the signature is similar to the Change Email Script.

{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "change_phone_number script does not exist",
  "errorCode": "auth0_idp_error"
}

The Auth0 dashboard does not support this script and must be updated using the patch connections management API. The entire options object must be included in the payload to avoid losing configuration for other connection settings. The sample connection payload below was redacted for brevity.

{
"options": {
    "customScripts": {
        "change_phone_number": "function changePhoneNumber(oldPhoneNumber, newPhoneNumber, verified, callback) { console.log(\"Update phone number called....\"); console.log (\"oldPhoneNumber:\", oldPhoneNumber); console.log (\"newPhoneNumber:\", newPhoneNumber);  console.log (\"verified:\", verified); console.log (\"callback:\", callback);   callback(null, true); \n}\n",
     // other scripts are removed for brevity
    },
    // other attributes are removed for brevity
  }
}