Passer au contenu principal
Si vous utilisez la structure de base de données hébergée par Auth0 pour stocker vos utilisateurs, vous pouvez tester la connexion en authentifiant des utilisateurs dans le même tenant ou dans un tenant distinct.

Tester lorsque l’importation des utilisateurs vers Auth0 est activée

Lorsque l’importation des utilisateurs est activée, les utilisateurs sont migrés progressivement de votre répertoire d’utilisateurs externe vers le répertoire d’utilisateurs d’Auth0. Pendant ce processus, les utilisateurs seront authentifiés auprès du répertoire externe la première fois qu’ils ouvriront une session avec succès. Toutes les tentatives de connexion suivantes seront effectuées auprès du répertoire d’utilisateurs d’Auth0. Pour en savoir plus, consultez la section sur les migrations automatiques dans Import and Export Users.

Créer un tenant et une application de test

  1. Utilisez le tableau de bord Auth0 pour créer un nouveau tenant.
  2. Accédez à Applications > Applications et créez une application Machine-to-Machine.
    Vous devez prendre en note le Client ID et le Client Secret lorsque vous créez les scripts de base de données personnalisés. Vous devez également prendre en note le Client ID pour activer les scopes dans l’API de gestion.
  3. Activez à la fois les types d’autorisation Password et Client Credential pour cette application (les deux doivent être activés pour ce test).
    Auth0 Dashboard > Applications > Advanced Settings
  4. Pour autoriser votre application, accédez à Applications > APIs.
  5. Sélectionnez API de gestion.
  6. Sous l’onglet Machine-to-Machine Applications, utilisez le bouton bascule pour autoriser votre application de test.
  7. Sélectionnez le menu déroulant pour activer les scopes suivants de l’API de gestion Auth0 :
    • read:users
    • update:users
    • delete:users
    • create:users
    • read:users_app_metadata
    • update:users_app_metadata
    • create:users_app_metadata
      Auth0 Dashboard > APIs > Management API >  M2M Tab > App Permissions

Créer des connexions de base de données de test

Après avoir créé un tenant et une application dans le Dashboard, créez une connexion de base de données source et une connexion de base de données cible.
  1. Accédez à Authentication > Database pour créer une nouvelle connexion de base de données qui servira de source.
  2. Donnez un nom à votre connexion source de test, activez Requires Username, puis sélectionnez Create.
    Vous pouvez créer des utilisateurs pour vos tests en accédant à User Management > Users. Après avoir sélectionné Create Users et rempli les champs requis, sélectionnez la base de données source dans le champ Connection.
  3. Créez une deuxième base de données qui servira de cible avec la même configuration qu’à l’étape 2.
    Vous pouvez définir la Password Policy sur Non-empty password required dans les bases de données source et cible afin d’utiliser des mots de passe simples dans vos tests.
  4. Dans votre base de données cible, passez à la vue Custom Database et activez Use my own database.
    Si vous voulez faire des tests avec Organizations et vos bases de données personnalisées, activez Context object in database scripts.
  5. Passez à la vue Settings et activez Import Users to Auth0.
  6. Passez à la vue Custom Database, puis repérez la section Database settings. Ajoutez les renseignements suivants à partir de votre base de données source créée à l’étape 1 :
KeyValue
client_idID client de l’application que vous avez créée.
client_secretSecret client de l’application que vous avez créée.
auth0_domainLe nom de votre tenant dans le domaine Auth0 : yourTenant.us.auth0.com.
source_databaseNom de la connexion source.
  1. Mettez à jour les scripts d’action de base de données Login et Get User dans votre base de données cible. Pour en savoir plus sur les pratiques exemplaires pour l’utilisation des scripts d’action de base de données, consultez Custom Database Connection and Action Scripts Best Practices.
  2. Sélectionnez Save and Try pour chaque script. Vous devriez surveiller la sortie console.log dans les journaux en temps réel d’Actions. Pour en savoir plus, consultez Actions Real-time Logs.
  3. Sélectionnez Try Connection pour tester la connexion en direct.

Tester sans activer Import Users

  1. Répétez les étapes de Créer un locataire et une application de test.
  2. Créez une connexion à une base de données de test.
  3. Assurez-vous que l’option Import Users to Auth0 est désactivée dans les paramètres de votre base de données source. Les utilisateurs s’authentifieront auprès du répertoire d’utilisateurs externe à chaque tentative de connexion.
  4. Mettez à jour tous les scripts d’action de la base de données à l’aide des exemples ci-dessous.

Script Get User

Le script Get User implémente une fonction exécutable qui détermine l’état actuel d’un utilisateur. Lorsque Import Users to Auth0 est activé, le script Get User s’exécute lorsqu’un utilisateur tente de s’inscrire pour vérifier si cet utilisateur existe déjà dans le répertoire d’utilisateurs externe. Le script Get User s’exécute aussi lorsqu’un utilisateur tente de :
  • Modifier l’adresse courriel d’un utilisateur (Change Email script)
  • Se connecter (Login script)
  • Modifier le mot de passe d’un utilisateur (Change Password script)
Lorsque Import Users to Auth0 est désactivé, le script Get User s’exécute lorsqu’un utilisateur tente de s’inscrire pour vérifier si cet utilisateur existe déjà dans le répertoire d’utilisateurs externe. Si l’utilisateur existe déjà dans le répertoire d’utilisateurs externe, le script Create ne sera pas exécuté. Le script Get User s’exécute aussi lorsqu’un utilisateur tente de :
  • Créer un utilisateur (Create script)
  • Modifier l’adresse courriel d’un utilisateur (Change Email script)
  • Modifier le mot de passe d’un utilisateur (Change Password script)

Exemple

async function getUser(user, context, callback) {
    log(`Script started.`);
    log(`Requesting an Access Token from "${configuration.auth0_domain}".`);
    let accessToken = await getAccessToken();
    accessToken = accessToken.access_token;
    if (!accessToken) return log(`Failed to get an Access Token from "${configuration.auth0_domain}".`, true);
    log(`The Access Token is available. Searching for user "${user}" in "${configuration.source_database}"`);
    user = user.toLowerCase();
    const searchQuery = encodeURI(`identities.connection:"${configuration.source_database}"+AND+(email:${user} OR username:${user})`);
    var options = {
        method: `GET`,
        url: `https://${configuration.auth0_domain}/api/v2/users?q=${searchQuery}`,
        headers: {
            Authorization: `Bearer ${accessToken}`,
        }
    };
    request(options, function (error, response) {
        if (error) return log(`Cannot connect to "${configuration.source_database}" database.`, true);
        let search_results = JSON.parse(response.body);
        let profile = null;
        if (search_results.length > 0) {
            log(`A user "${user}" is FOUND in "${configuration.source_database}" database.`);
            profile = {
                user_id: search_results[0].user_id.toString(),
                nickname: search_results[0].nickname,
                username: search_results[0].username,
                email: search_results[0].email
            };
        } else {
            log(`A user "${user}" is NOT FOUND in "${configuration.source_database}" database.`);
        }
        log(`Script completed!`);
        return callback(null, profile);
    });
    /* -- OBTENIR UN JETON D'ACCÈS VIA LES IDENTIFIANTS CLIENT -- */
    async function getAccessToken() {
        var options = {
            method: `POST`,
            url: `https://${configuration.auth0_domain}/oauth/token`,
            headers: {
                "Content-Type": `application/x-www-form-urlencoded`,
            },
            form: {
                grant_type: `client_credentials`,
                client_id: configuration.client_id,
                client_secret: configuration.client_secret,
                audience: `https://${configuration.auth0_domain}/api/v2/`
            },
            json: true
        };
        return new Promise(function (resolve) {
            request(options, function (error, response) {
                resolve(error || response.body);
            });
        });
    }
    /* -- JOURNALISATION -- */
    function log(message, error = false) {
        const script_name = `GET USER`;
        const error_label = error ? `(ERROR)` : ``;
        const return_message = `${script_name}: ${error_label} ${message}`;
        console.log(return_message);
        if (error) return callback(new Error(return_message));
    }
}

Script de connexion

Le script Login implémente une fonction exécutable qui authentifie un utilisateur lorsqu’il ouvre une session. Si l’utilisateur existe dans la base de données cible (Auth0), il l’authentifie à l’aide de cet enregistrement. Sinon, il authentifie l’utilisateur à l’aide de son enregistrement dans la base de données source (externe).

Exemple

function login(usernameOrEmail, password, context, callback) {
  log(`Script started.`);
  const jwt = require('jsonwebtoken');
  const options = {
    method: `POST`,
    url: `https://${configuration.auth0_domain}/oauth/token`,
    headers: { "Content-Type": `application/x-www-form-urlencoded` },
    json: true,
    form: {
      grant_type: `http://auth0.com/oauth/grant-type/password-realm`,
      client_id: configuration.client_id,
      client_secret: configuration.client_secret,
      username: usernameOrEmail,
      password: password,
      realm: `${configuration.source_database}`
    }
  };
  request(options, function (error, response, body) {
    log(`Attempting to authenticate a user "${usernameOrEmail}" against "${configuration.source_database}" database in "${configuration.auth0_domain}" tenant.`);
    if (error) return log(`Cannot connect to "${configuration.auth0_domain}" database.`, true);
    if (response.statusCode !== 200) {
      console.log(`LOGIN: (ERROR) ${response.body.error_description}`);
      return callback(new WrongUsernameOrPasswordError(usernameOrEmail, `LOGIN: (ERROR) ${response.body.error_description}`));
    }
    log(`Successfuly authenticated user "${usernameOrEmail}" against "${configuration.source_database}" database in "${configuration.auth0_domain}" tenant.`);
    const decoded_id_token = jwt.decode(body.id_token);
    const profile = {
      user_id: decoded_id_token.sub,
      nickname: decoded_id_token.nickname,
      username: decoded_id_token.username,
      email: decoded_id_token.email
    };
    log(`Script completed.`);
    return callback(null, profile);
  });
  /* -- JOURNALISATION -- */
  function log(message, error = false) {
    const script_name = `LOGIN`;
    const error_label = error ? `(ERROR)` : ``;
    const return_message = `${script_name}: ${error_label} ${message}`;
    console.log(return_message);
    if (error) return callback(new Error(return_message));
  }
}

Script de création

Le script de création contient une fonction exécutable qui crée un enregistrement utilisateur correspondant dans la base de données externe lorsqu’un utilisateur s’inscrit au moyen de , ou est créé dans le ou à l’aide de l’ d’Auth0.

Exemple

async function create(user, context, callback) {
  log(`Script started.`);
  log(`Requesting an Access Token from "${configuration.auth0_domain}".`);
  let accessToken = await getAccessToken();
  if (!accessToken.access_token) return log(`Failed to get an Access Token from "${configuration.auth0_domain}".`, true);
  accessToken = accessToken.access_token;
  log(`The Access Token is available. Attempting to create a user "${user.email}" in "${configuration.source_database}"`);
  const options = {
    method: `POST`,
    url: `https://${configuration.auth0_domain}/api/v2/users`,
    headers: {
      Authorization: `Bearer ${accessToken}`,
      "Content-Type": `application/x-www-form-urlencoded`
    },
    form: {
      connection: configuration.source_database,
      email: user.email,
      password: user.password,
      username: user.username
    },
    json: true
  };
  request(options, function (error, response) {
    if (error) return log(`Cannot connect to "${configuration.source_database}" database.`, true);
    switch (response.statusCode) {
      case 201:
        log(`The user "${user.email}" is successfuly created in "${configuration.source_database}" database.`);
        return callback(null);
      case 409:
        return callback(new ValidationError(`user_exists`, `The user already exists in "${configuration.source_database}" database.`));
      default:
        return log(`Failed to create a user "${user.email}" in "${configuration.source_database}" database. Error: "${response.statusCode}, ${response.body.message}"`, true);
    }
  });
  /* -- OBTENIR UN JETON D'ACCÈS VIA L'IDENTIFIANT CLIENT -- */
  async function getAccessToken() {
    var options = {
      method: `POST`,
      url: `https://${configuration.auth0_domain}/oauth/token`,
      headers: {
        "Content-Type": `application/x-www-form-urlencoded`,
      },
      form: {
        grant_type: `client_credentials`,
        client_id: configuration.client_id,
        client_secret: configuration.client_secret,
        audience: `https://${configuration.auth0_domain}/api/v2/`
      },
      json: true
    };
    return new Promise(function (resolve) {
      request(options, function (error, response) {
        resolve(error || response.body);
      });
    });
  }
  /* -- JOURNALISATION -- */
  function log(message, error = false) {
    const script_name = `CREATE`;
    const error_label = error ? `(ERROR)` : ``;
    const return_message = `${script_name}: ${error_label} ${message}`;
    console.log(return_message);
    if (error) return callback(new Error(return_message));
  }
}

Script de suppression

Le script de suppression exécute une fonction qui supprime un utilisateur d’Auth0 et de la base de données externe en une seule opération lorsque l’utilisateur est supprimé dans le tableau de bord Auth0 ou à l’aide de l’API de gestion Auth0.

Exemple

async function deleteUser(user, context, callback) {
  log(`Script started.`);
  log(`Requesting an Access Token from "${configuration.auth0_domain}".`);
  let accessToken = await getAccessToken();
  if (!accessToken.access_token) return log(`Failed to get an Access Token from "${configuration.auth0_domain}".`, true);
  accessToken = accessToken.access_token;
  log(`The Access Token is available. Attempting to delete a user "${user}" from "${configuration.source_database}"`);
  const options = {
    method: `DELETE`,
    url: `https://${configuration.auth0_domain}/api/v2/users/${user}`,
    headers: {
      Authorization: `Bearer ${accessToken}`,
      "Content-Type": `application/x-www-form-urlencoded`
    },
    json: true
  };
  request(options, function (error, response) {
    if (error) return log(`Cannot connect to "${configuration.source_database}" database.`, true);
    switch (response.statusCode) {
      case 204:
        log(`The user "${user}" is successfuly deleted from "${configuration.source_database}" database.`);
        return callback(null);
      default:
        return log(`Failed to delete a user "${user}" from "${configuration.source_database}" database. Error: "${response.statusCode}, ${response.body.message}"`, true);
    }
  });
  /* -- OBTENIR UN JETON D'ACCÈS VIA L'IDENTIFIANT CLIENT -- */
  async function getAccessToken() {
    var options = {
      method: `POST`,
      url: `https://${configuration.auth0_domain}/oauth/token`,
      headers: {
        "Content-Type": `application/x-www-form-urlencoded`,
      },
      form: {
        grant_type: `client_credentials`,
        client_id: configuration.client_id,
        client_secret: configuration.client_secret,
        audience: `https://${configuration.auth0_domain}/api/v2/`
      },
      json: true
    };
    return new Promise(function (resolve) {
      request(options, function (error, response) {
        resolve(error || response.body);
      });
    });
  }
  /* -- JOURNALISATION -- */
  function log(message, error = false) {
    const script_name = `DELETE`;
    const error_label = error ? `(ERROR)` : ``;
    const return_message = `${script_name}: ${error_label} ${message}`;
    console.log(return_message);
    if (error) return callback(new Error(return_message));
  }
}

Script de vérification

Le script de vérification implémente une fonction exécutable qui met à jour l’état de vérification de l’adresse courriel d’un utilisateur dans la base de données externe lorsque l’utilisateur clique sur le lien dans le courriel de vérification envoyé par Auth0.

Exemple

async function verify(user, context, callback) {
  log(`Script started.`);
  log(`Requesting an Access Token from "${configuration.auth0_domain}".`);
  let accessToken = await getAccessToken();
  if (!accessToken.access_token) return log(`Failed to get an Access Token from "${configuration.auth0_domain}".`, true);
  accessToken = accessToken.access_token;
  log(`The Access Token is available. Searching for user "${user}" in "${configuration.source_database}"`);
  user = user.toLowerCase();
  const searchQuery = encodeURI(`identities.connection:"${configuration.source_database}"+AND+(email:${user} OR username:${user})`);
  var options = {
    method: `GET`,
    url: `https://${configuration.auth0_domain}/api/v2/users?q=${searchQuery}`,
    headers: {
      Authorization: `Bearer ${accessToken}`,
    }
  };
  request(options, function (error, response) {
    if (error) return log(`Cannot connect to "${configuration.source_database}" database.`, true);
    let search_results = JSON.parse(response.body);
    if (search_results.length > 0) {
      log(`A user "${user}" is found in "${configuration.source_database}" database.`);
      const user_id = search_results[0].user_id.toString();
      log(`Attempting to mark user "${user_id}" as verified in "${configuration.source_database}" database`);
      const options = {
        method: `PATCH`,
        url: `https://${configuration.auth0_domain}/api/v2/users/${user_id}`,
        headers: {
          Authorization: `Bearer ${accessToken}`,
          "Content-Type": `application/x-www-form-urlencoded`
        },
        form: {
          email_verified: true,
        },
        json: true
      };
      request(options, function (error, response) {
        if (error) return log(`Cannot connect to "${configuration.source_database}" database.`, true);
        switch (response.statusCode) {
          case 200:
            log(`The user "${user}" is marked as verified in "${configuration.source_database}" database.`);
            return callback(null, true);
          default:
            return log(`Failed to mark a user "${user}" as verified in "${configuration.source_database}" database. Error: "${response.statusCode}, ${response.body.message}"`, true);
        }
      });
    } else {
      log(`A user "${user}" is not found in "${configuration.source_database}" database. Unable to verify.`, true);
    }
  });
  /* -- OBTENIR UN JETON D'ACCÈS VIA L'IDENTIFIANT CLIENT -- */
  async function getAccessToken() {
    var options = {
      method: `POST`,
      url: `https://${configuration.auth0_domain}/oauth/token`,
      headers: {
        "Content-Type": `application/x-www-form-urlencoded`,
      },
      form: {
        grant_type: `client_credentials`,
        client_id: configuration.client_id,
        client_secret: configuration.client_secret,
        audience: `https://${configuration.auth0_domain}/api/v2/`
      },
      json: true
    };
    return new Promise(function (resolve) {
      request(options, function (error, response) {
        resolve(error || response.body);
      });
    });
  }
  /* -- JOURNALISATION -- */
  function log(message, error = false) {
    const script_name = `VERIFY`;
    const error_label = error ? `(ERROR)` : ``;
    const return_message = `${script_name}: ${error_label} ${message}`;
    console.log(return_message);
    if (error) return callback(new Error(return_message));
  }
}

Script de changement de mot de passe

Le script de changement de mot de passe implémente une fonction exécutable qui met à jour le mot de passe d’un utilisateur dans la base de données externe lorsqu’un processus de changement de mot de passe est lancé depuis le tableau de bord Auth0 ou l’API de gestion Auth0.

Exemple

async function changePassword(user, newPassword, context, callback) {
  log(`Script started.`);
  log(`Requesting an Access Token from "${configuration.auth0_domain}".`);
  let accessToken = await getAccessToken();
  if (!accessToken.access_token) return log(`Failed to get an Access Token from "${configuration.auth0_domain}".`, true);
  accessToken = accessToken.access_token;
  log(`The Access Token is available. Searching for user "${user}" in "${configuration.source_database}" database.`);
  user = user.toLowerCase();
  const searchQuery = encodeURI(`identities.connection:"${configuration.source_database}"+AND+(email:${user} OR username:${user})`);
  var options = {
    method: `GET`,
    url: `https://${configuration.auth0_domain}/api/v2/users?q=${searchQuery}`,
    headers: {
      Authorization: `Bearer ${accessToken}`,
    }
  };
  request(options, function (error, response) {
    if (error) return log(`Cannot connect to "${configuration.source_database}" database.`, true);
    let search_results = JSON.parse(response.body);
    if (search_results.length > 0) {
      log(`A user "${user}" is found in "${configuration.source_database}" database.`);
      const user_id = search_results[0].user_id.toString();
      log(`Attempting to change password for user "${user_id}" in "${configuration.source_database}" database.`);
      const options = {
        method: `PATCH`,
        url: `https://${configuration.auth0_domain}/api/v2/users/${user_id}`,
        headers: {
          Authorization: `Bearer ${accessToken}`,
          "Content-Type": `application/x-www-form-urlencoded`
        },
        form: {
          password: newPassword,
        },
        json: true
      };
      request(options, function (error, response) {
        if (error) return log(`Cannot connect to "${configuration.source_database}" database.`, true);
        switch (response.statusCode) {
          case 200:
            log(`The user "${user}" password successfully changed in "${configuration.source_database}" database.`);
            return callback(null, true);
          default:
            return log(`Failed to change password for "${user}"  in "${configuration.source_database}" database. Error: "${response.statusCode}, ${response.body.message}"`, true);
        }
      });
    } else {
      log(`A user "${user}" is not found in "${configuration.source_database}" database. Unable to change password.`, true);
    }
  });
  /* -- OBTENIR UN JETON D'ACCÈS VIA L'IDENTIFIANT CLIENT -- */
  async function getAccessToken() {
    var options = {
      method: `POST`,
      url: `https://${configuration.auth0_domain}/oauth/token`,
      headers: {
        "Content-Type": `application/x-www-form-urlencoded`,
      },
      form: {
        grant_type: `client_credentials`,
        client_id: configuration.client_id,
        client_secret: configuration.client_secret,
        audience: `https://${configuration.auth0_domain}/api/v2/`
      },
      json: true
    };
    return new Promise(function (resolve) {
      request(options, function (error, response) {
        resolve(error || response.body);
      });
    });
  }
  /* -- JOURNALISATION -- */
  function log(message, error = false) {
    const script_name = `CHANGE PASSWORD`;
    const error_label = error ? `(ERROR)` : ``;
    const return_message = `${script_name}: ${error_label} ${message}`;
    console.log(return_message);
    if (error) return callback(new Error(return_message));
  }
}

Script Change Email

Le script Change Email exécute une fonction qui met à jour l’adresse courriel d’un utilisateur lorsque celui-ci modifie son adresse courriel ou que l’état de vérification de celle-ci change. Ce script n’est pas disponible dans le tableau de bord Auth0. Vous devez appeler le point de terminaison Update a connection de l’API de gestion et fournir la propriété options.customScripts.change_email.

Exemple

async function changeEmail(user, newEmail, verified, callback) {
  log(`Script started.`);
  log(`Requesting an Access Token from "${configuration.auth0_domain}".`);
  let accessToken = await getAccessToken();
  if (!accessToken.access_token) return log(`Failed to get an Access Token from "${configuration.auth0_domain}".`, true);
  accessToken = accessToken.access_token;
  log(`The Access Token is available. Searching for user "${user}" in "${configuration.source_database}" database.`);
  user = user.toLowerCase();
  const searchQuery = encodeURI(`identities.connection:"${configuration.source_database}"+AND+(email:${user} OR username:${user})`);
  var options = {
    method: `GET`,
    url: `https://${configuration.auth0_domain}/api/v2/users?q=${searchQuery}`,
    headers: {
      Authorization: `Bearer ${accessToken}`,
    }
  };
  request(options, function (error, response) {
    if (error) return log(`Cannot connect to "${configuration.source_database}" database.`, true);
    let search_results = JSON.parse(response.body);
    if (search_results.length > 0) {
      log(`A user "${user}" is found in "${configuration.source_database}" database.`);
      const user_id = search_results[0].user_id.toString();
      log(`Attempting to change email / verified status for user "${user_id}" in "${configuration.source_database}" database.`);
      const options = {
        method: `PATCH`,
        url: `https://${configuration.auth0_domain}/api/v2/users/${user_id}`,
        headers: {
          Authorization: `Bearer ${accessToken}`,
          "Content-Type": `application/x-www-form-urlencoded`
        },
        form: {
          email: newEmail,
          email_verified: verified || false
        },
        json: true
      };
      request(options, function (error, response) {
        if (error) return log(`Cannot connect to "${configuration.source_database}" database.`, true);
        switch (response.statusCode) {
          case 200:
            log(`The user "${user}" email / verified status successfully changed in "${configuration.source_database}" database.`);
            return callback(null, true);
          default:
            return log(`Failed to change email / verified status for "${user}"  in "${configuration.source_database}" database. Error: "${response.statusCode}, ${response.body.message}"`, true);
        }
      });
    } else {
      log(`A user "${user}" is not found in "${configuration.source_database}" database. Unable to change email / verified status.`, true);
    }
  });
  /* -- OBTENIR UN JETON D'ACCÈS VIA L'IDENTIFIANT CLIENT -- */
  async function getAccessToken() {
    var options = {
      method: `POST`,
      url: `https://${configuration.auth0_domain}/oauth/token`,
      headers: {
        "Content-Type": `application/x-www-form-urlencoded`,
      },
      form: {
        grant_type: `client_credentials`,
        client_id: configuration.client_id,
        client_secret: configuration.client_secret,
        audience: `https://${configuration.auth0_domain}/api/v2/`
      },
      json: true
    };
    return new Promise(function (resolve) {
      request(options, function (error, response) {
        resolve(error || response.body);
      });
    });
  }
  /* -- JOURNALISATION -- */
  function log(message, error = false) {
    const script_name = `CHANGE EMAIL`;
    const error_label = error ? `(ERROR)` : ``;
    const return_message = `${script_name}: ${error_label} ${message}`;
    console.log(return_message);
    if (error) return callback(new Error(return_message));
  }
}

Pour en savoir plus