Skip to main content
When using Multiple Custom Domains with the Delegated Administration Extension, the Custom Domain Hook allows you to specify which custom domain should be used for user operations such as creating users, resetting passwords, verifying emails, and blocking users. This hook is particularly useful in multi-tenant or multi-brand environments where different users should receive communications from different custom domains based on their organization, email domain, or other attributes.

Hook contract

  • ctx: Context object containing information about the current request.
    • method: The operation being performed (e.g., create, reset_password, verify_email, block_user).
    • payload: Data related to the operation (for create method, contains user details like email).
    • request: Contains information about the request.
      • originalUser: The user being operated on (for methods other than create).
  • callback(error, result): Callback function to return the custom domain configuration.
    • error: Error object if something went wrong, otherwise null.
    • result: Object specifying the custom domain behavior:
      • customDomain (string): The custom domain to use (e.g., 'customone.example.com').
      • useCanonicalDomain (boolean): Set to true to use the tenant’s canonical domain instead of a custom domain.
      • Return empty object {} to delegate to the tenant’s default domain.

Supported methods

The Custom Domain Hook is invoked for the following user operations:
  • create: When creating a new user
  • reset_password: When sending a password reset email
  • verify_email: When sending an email verification link
  • block_user: When blocking a user

Sample use

In this example, users from different email domains are routed to different custom domains. Users from a corporate domain use the canonical tenant domain, while all others use the tenant’s default domain.
function(ctx, callback) {
  // Map email domains to custom domains
  const emailToDomain = {
    'customone.com': 'customone.example.com',
    'customtwo.com': 'customtwo.example.com',
  };

  // Helper to extract custom domain from email
  function getDomainFromEmail(userEmail) {
    if (!userEmail) return null;
    const domain = userEmail.split('@')[1];
    return emailToDomain[domain];
  }

  // Helper to determine if canonical domain should be used
  function shouldUseCanonical(userEmail) {
    if (!userEmail) return false;
    const domain = userEmail.split('@')[1];
    return domain === 'corp.com';
  }

  // Get user email based on the operation
  let userEmail;
  if (ctx.method === 'create') {
    // For create operations, email is in the payload
    userEmail = ctx.payload.email;
  } else {
    // For other operations, get email from the original user
    userEmail = ctx.request.originalUser.email;
  }

  const customDomain = getDomainFromEmail(userEmail);

  // Option 1: Use a specific custom domain
  if (customDomain) {
    return callback(null, {
      customDomain: customDomain
    });
  }

  // Option 2: Use the canonical tenant domain
  if (shouldUseCanonical(userEmail)) {
    return callback(null, {
      useCanonicalDomain: true
    });
  }

  // Option 3: Use tenant's default domain (if configured)
  // Return empty object to delegate to the default domain
  return callback(null, {});
}

Notes

  • If this hook is not configured, the Delegated Administration Extension will use the tenant’s default custom domain if one is configured, or the canonical domain otherwise.
  • The custom domain returned must be a verified custom domain configured in your tenant. If you specify an invalid or unverified domain, the operation will fail.
  • When using useCanonicalDomain: true, emails and links will use your Auth0 tenant’s canonical domain (e.g., YOUR_TENANT.auth0.com or YOUR_TENANT.REGION.auth0.com).
  • Returning an empty object {} delegates the domain selection to the tenant’s default custom domain configuration.

Learn more