Custom Phone Provider Action Receives an Incomplete Event Object

Overview

This article explains why the event object passed to a Custom Phone Provider Action trigger may be incomplete. This occurs in two main scenarios: during a passwordless or Multi-Factor Authentication (MFA) flow, and when a user is created via the Management API for asms connection without the phone_verified property being set to true. In these cases, properties on the event object, such as userorganization, and connection, are observed to be undefined.

Applies To

  • Auth0 Actions
  • Custom Phone Provider
  • Passwordless Connections
  • Multi-Factor Authentication (MFA)
  • Management API

Cause

This behaviour is a known limitation. While the official event object documentation for the Custom Phone Provider trigger depicts a complete event object, in practice, it is not fully populated in all scenarios. The Action is executed at a point in the authentication or user creation pipeline where the full context, including the complete user profile and organisation details, has not yet been loaded. 

Solution

To access the complete user profile within the Action, use the Auth0 Management API to fetch the user by their phone number. The phone number is reliably available in event.recipient.

The custom-phone-provider Action can be configured in the Auth0 Dashboard by navigating to Branding > Phone Provider. Please note that it is not available in the main Actions library.

  1. Ensure a Machine-to-Machine (M2M) application is authorised to call the Auth0 Management API with the read:users permission.
  2. Add the Domain, Client ID, and Client Secret of the M2M application to the Secrets section of the Action editor.
  3. Add the auth0 Node.js package as a dependency in the Modules section of the Action editor.
  4. Use the following code as a starting point within the onExecuteCustomPhoneProvider function to fetch the complete user profile.
    exports.onExecuteCustomPhoneProvider = async (event, api) => {
      const { ManagementClient } = require('auth0');
    
      const management = new ManagementClient({
        domain: event.secrets.domain,
        clientId: event.secrets.clientId,
        clientSecret: event.secrets.clientSecret,
      });
    
      // The phone number is reliably available in event.recipient.
      const phoneNumber = event.recipient;
    
      if (!phoneNumber) {
        console.log("Recipient phone number not found in the event.");
        return;
      }
    
      try {
        const users = await management.users.getAll({
          q: `phone_number:"${phoneNumber}"`
        });
    
        if (users.data.length === 0) {
          console.log(`No user found with phone number: ${phoneNumber}`);
          return;
        }
    
        // Use the first user found. Note: A phone number may not be unique.
        const user = users.data[0];
    
        console.log("Successfully fetched full user profile:", user);
        // The full user profile is now available in the 'user' object.
    
      } catch (error) {
        console.error("Error fetching user by phone number:", error);
      }
    };
 

Management API Rate Limits

This solution uses the Management API to fetch user details. Customers implementing this workaround should be mindful of their tenant's Management API rate limits. High-traffic scenarios could lead to rate limit exhaustion, impacting other services that rely on the Management API. It is crucial to monitor API usage and ensure that the limit is sufficient to handle this additional load.

Recommended content

No recommended content found...