Connection Level Email Verification

Problem statement

How to perform email verification at the connection level. Currently this can only be set at a tenant level to on or off.

Cause

Sometimes a customer will have a connection which will have ‘untrusted’ end users where email verification is needed, but not subject other connections on the tenant to the same requirement

Solution

There are 2 ways to enforce email verification for specific connections only (not tenant level). The main drawback to these methods is: Users need to be signed up using the Management API create users endpoint only. The signup form in the Universal login needs to be disabled as it will always send verification emails if used.

The options are to perform the selective logic for email verification in:

  1. An Action within the tenant (benefit is you can integrate the email sending with the login flows, resend emails if necessary)
  2. Upon signup using external form/application/batch script (benefit is it is simpler to implement)

Option 1 Implementation :

  • End users need to be created using the Management API only (not the signup form) with the parameter verify_email: false (Create a User ). The signup form does not provide a way to prevent verification emails from being sent.
  • Once the user is created you can selectively send verification emails using a call to the Management API’s Send Verification Email Job endpoint
    • This can be triggered using an Action when the user attempts to login with the following example code. It will prevent users from getting into the application until verified and send an email verification on every attempt:
const ManagementClient = require('auth0').ManagementClient;
/**
* Handler that will be called during the execution of a PostLogin flow.
*
* @param {Event} event - Details about the user and the context in which they are logging in.
* @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
*/
exports.onExecutePostLogin = async (event, api) => {
  const logHeader = ' --- Send Email Verification email for specific connection users --- ';
  console.log(logHeader+' START');

  if (event.user.email_verified === true) {
    console.log(logHeader+' Email already verified');
    return;
  }

  const connection_list = [
    "Username-Password-Authentication"
  ];

  if (connection_list.includes(event.connection.name)) {
    console.log(logHeader+' Sending email verification for '+event.user.email);
    const managementClientInstance = new ManagementClient({
      domain: event.secrets.AUTH0_DOMAIN,
      clientId: event.secrets.AUTH0_IMPORT_CLIENT_ID,
      clientSecret: event.secrets.AUTH0_IMPORT_CLIENT_SECRET,
      scope: "update:users"
    });
  
    managementClientInstance.jobs.verifyEmail(
      { user_id: event.user.user_id,
      identity: {
        user_id: event.user.user_id.split("|").pop(),
        provider: "auth0"
      }}
    );
    api.access.deny("Please verify your email first");
  }

};

Option 2 Implementation:
This depends on the end users code preferences but the general flow is the following:

  • Signup user(s) using the Management API (Create a User) with the following parameter set:
    • If user verification not desired then: verify_email: false
    • If the verification is desired then don’t set or set verify_email: true (default)

NOTE: This method can also be used for Application level email verification by modifying the connection_list variable above to another variable (such as application_list ) with the application ids instead and change the event.connection.name to event.client.name (See Actions Triggers: post-login - Event Object). The above code will likely need tweaking and testing if used in production.