> ## Documentation Index
> Fetch the complete documentation index at: https://translations.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Décrit les modèles de script d’action de base de données personnalisée pour la connexion des utilisateurs.

# Modèles de script de connexion

Le script Login implémente la fonction exécutée chaque fois qu’un utilisateur doit s’authentifier. Nous vous recommandons de nommer cette fonction `login`.

Ce script est requis à la fois pour l’authentification héritée et pour la [migration automatique](/fr-CA/docs/manage-users/user-migration/configure-automatic-migration-from-your-database). Si la migration automatique est configurée pour la connexion, le processus de migration se déclenche après la première connexion réussie de l’utilisateur. Auth0 recommande de définir un `user_id` permanent dans le profil utilisateur renvoyé afin d’éviter la création d’utilisateurs en double.

<div id="login-function">
  ## Fonction `login`
</div>

La fonction `login` doit :

* Envoyer les informations d’identification fournies de l’utilisateur à l’API de la base de données externe.
* Retourner les données de profil de l’utilisateur si l’authentification réussit.
* Retourner une erreur si l’authentification échoue.

<div id="definition">
  ### Définition
</div>

La fonction `login` accepte trois paramètres et renvoie une fonction de rappel :

```js lines theme={null}
login(userNameOrEmail, password, callback): function
```

| Paramètre         | Type     | Description                                                                  |
| ----------------- | -------- | ---------------------------------------------------------------------------- |
| `userNameOrEmail` | String   | Le nom d’utilisateur ou le courriel de l’utilisateur.                        |
| `password`        | String   | Le mot de passe de l’utilisateur en texte brut.                              |
| `callback`        | Function | Permet de transmettre des erreurs ou des données de profil dans le pipeline. |

### Exemple

Voici un exemple en pseudo-JavaScript montrant comment vous pourriez implémenter la fonction `login`. Pour des exemples propres à chaque langage, consultez [Exemples de scripts propres à chaque langage](#language-specific-script-examples).

```javascript lines expandable theme={null}
function login(userNameOrEmail, password, callback) {
  // Envoyer les identifiants à l'API de base de données externe
  let hashedPassword = hash(password);

  let options = {
    url: "https://example.com/api/authenticate",
    body: {
      email: userNameOrEmail,
      password: hashedPassword
    }
  };

  send(options, (err, profileData) => {
    // Retourner une erreur dans le rappel si l'authentification échoue
    if (err) {
      return callback(new WrongUsernameOrPasswordError(userNameOrEmail, "My custom error message."));
    } else {
      // Retourner les données du profil dans le rappel si l'authentification réussit
      let profile = {
        username: profileData.username,
        email: profileData.emailAddress,
        user_id: profileData.userId
      };

      return callback(null, profile);
    }
  });
}
```

<div id="encryption">
  ### Chiffrement
</div>

<Warning>
  Évitez de journaliser, de stocker ou de transmettre le mot de passe sous une forme non chiffrée, où que ce soit.
</Warning>

Chiffrez la valeur `password` à l’aide d’une bibliothèque de hachage cryptographique telle que `bcrypt` afin d’éviter toute fuite potentielle de données.

#### Exemple

```js lines theme={null}
bcrypt.hash(password, 10, function (err, hash) {
    if (err) {
        return callback(err);
    } else {
        // Retourner le mot de passe haché
    }
});
```

<div id="callback-function">
  ## Fonction de rappel
</div>

La fonction `callback` sert à transmettre les données de profil de l’utilisateur ou les données d’erreur au sein du pipeline.

<div id="definition">
  ### Définition
</div>

La fonction `callback` accepte jusqu’à deux paramètres et renvoie une fonction :

```js lines theme={null}
callback(error[, profile]): function
```

| Paramètre | Type   | Obligatoire | Description                                      |
| --------- | ------ | ----------- | ------------------------------------------------ |
| `error`   | Object | Obligatoire | Contient les données d’erreur.                   |
| `profile` | Object | Facultatif  | Contient les données du profil de l’utilisateur. |

<div id="return-the-user-profile">
  ### Retourner le profil de l’utilisateur
</div>

<Warning>
  Les données de profil renvoyées par le script Login pour un utilisateur doivent être cohérentes avec celles renvoyées par le script Get User.
</Warning>

Si l’utilisateur s’authentifie avec succès, ses données de profil doivent être renvoyées dans l’objet `profile` sous [forme normalisée](/fr-CA/docs/manage-users/user-accounts/user-profiles/normalized-user-profile-schema). En plus des champs standard, vous pouvez inclure les champs `user_metadata`, `app_metadata` et `mfa_factors`.

#### Exemple

```js lines theme={null}
return callback(null, {
    username: "username",
    user_id: "my-custom-db|username@domain.com",
    email: "username@domain.com",
    email_verified: false,
    user_metadata: {
        language: "en"
    },
    app_metadata: {
        plan: "full"
    },
    mfa_factors: [
      {
        phone: {
          value: "+15551234567"
        }
      },
    ]
});
```

<div id="return-an-error">
  ### Renvoyer une erreur
</div>

Si une erreur se produit, le paramètre `error` doit contenir les renseignements pertinents sur le problème survenu.

<div id="wrongusernameorpassworderror-type-object">
  #### Objet du type `WrongUsernameOrPasswordError`
</div>

L’objet de type d’erreur personnalisée `WrongUsernameOrPasswordError` vous permet de transmettre des données qui seront affichées dans les [journaux du locataire](/fr-CA/docs/deploy-monitor/logs).

<div id="constructor">
  ##### Constructeur
</div>

Le constructeur `WrongUsernameOrPasswordError` accepte jusqu’à deux paramètres :

```js wrap lines theme={null}
new WrongUsernameOrPasswordError(userNameOrEmail[, message]): WrongUsernameOrPasswordError
```

| Paramètre         | Type   | Obligatoire | Description                                                                         |
| ----------------- | ------ | ----------- | ----------------------------------------------------------------------------------- |
| `userNameOrEmail` | String | Obligatoire | Contient le nom d’utilisateur ou le courriel de l’utilisateur, ou la valeur `null`. |
| `message`         | String | Facultatif  | Contient de l’information sur l’erreur.                                             |

<div id="return-error-with-username-or-email">
  #### Retourner une erreur avec un nom d’utilisateur ou un courriel
</div>

Si vous retournez une erreur contenant une valeur pour le champ `userNameOrEmail`, Auth0 consignera un événement de journal du locataire `fp`.

<div id="example">
  ##### Exemple
</div>

```js wrap lines theme={null}
return callback(new WrongUsernameOrPasswordError(userNameOrEmail, "My custom error message"));
```

| champ de l’événement du journal du locataire | Valeur                                   |
| -------------------------------------------- | ---------------------------------------- |
| **Code**                                     | `fp`                                     |
| **Événement**                                | Échec de connexion (mot de passe erroné) |
| **Description**                              | `My custom error message`                |

<div id="return-error-without-username-or-email">
  #### Retourner une erreur sans nom d’utilisateur ni courriel
</div>

Si vous retournez une erreur avec une valeur `null` pour le champ `userNameOrEmail`, Auth0 consignera un événement de journal du locataire `fu`.

<div id="example">
  ##### Exemple
</div>

```js wrap lines theme={null}
return callback(new WrongUsernameOrPasswordError(null, "My custom error message"));
```

| Champ de l’événement du journal du locataire | Valeur                                                   |
| -------------------------------------------- | -------------------------------------------------------- |
| **Code**                                     | `fu`                                                     |
| **Événement**                                | Échec de connexion (courriel/nom d’utilisateur invalide) |
| **Description**                              | `Mon message d’erreur personnalisé`                      |

<div id="sync-user-profile-attributes-at-each-login">
  ## Synchroniser les attributs du profil de l’utilisateur à chaque connexion
</div>

Activez le paramètre **Sync user profile attributes at each login** si vous voulez qu’Auth0 mette à jour les champs `name`, `nickname`, `given_name`, `family_name` et/ou `picture` avec les valeurs renvoyées par la base de données externe à chaque connexion.

Si vous n’activez pas ce paramètre, les valeurs renvoyées par la base de données externe lors de la première connexion de l’utilisateur seront conservées aux connexions suivantes, même si elles ont changé dans la base de données externe.

<div id="language-specific-script-examples">
  ## Exemples de scripts par langage
</div>

Auth0 fournit des scripts d’exemple pour les langages/technologies suivants :

* [JavaScript](#javascript)
* [ASP.NET Membership Provider (MVC3 - Universal Providers)](#asp-net-membership-provider-mvc3-universal-providers-)
* [ASP.NET Membership Provider (MVC4 - Simple Membership)](#asp-net-membership-provider-mvc4-simple-membership-)
* [MongoDB](#mongodb)
* [MySQL](#mysql)
* [PostgreSQL](#postgresql)
* [SQL Server](#sql-server)
* [Windows Azure SQL Database](#windows-azure-sql-database)
* [Axios](#axios)
* [Stormpath](#stormpath)

<div id="javascript">
  ### JavaScript
</div>

```javascript lines expandable theme={null}
function login(email, password, callback) {
  // Ce script doit authentifier un utilisateur à partir des informations d'identification stockées dans
  // votre base de données.
  // Il est exécuté lorsqu'un utilisateur tente de se connecter ou immédiatement après l'inscription
  // (à titre de vérification que l'utilisateur s'est bien inscrit).
  //
  // Tout ce que ce script retourne sera défini dans le profil de l'utilisateur
  // et sera visible par tous les administrateurs du locataire. Évitez d'ajouter des attributs
  // avec des valeurs telles que des mots de passe, des clés, des secrets, etc.
  //
  // Le paramètre `password` de cette fonction est en texte brut. Il doit être
  // haché/salé pour correspondre à ce qui est stocké dans votre base de données. Par exemple :
  //
  //     var bcrypt = require('bcrypt@0.8.5');
  //     bcrypt.compare(password, dbPasswordHash, function(err, res)) { ... }
  //
  // Ce script peut se terminer de trois façons :
  // 1. Les informations d'identification de l'utilisateur sont valides. Le profil utilisateur retourné doit être au
  // format suivant : https://auth0.com/docs/users/normalized/auth0/normalized-user-profile-schema
  //     var profile = {
  //       user_id: ..., // user_id est obligatoire
  //       email: ...,
  //       [...]
  //     };
  //     callback(null, profile);
  // 2. Les informations d'identification de l'utilisateur sont invalides
  //     callback(new WrongUsernameOrPasswordError(email, "my error message"));
  // 3. Une erreur s'est produite lors de la tentative d'accès à votre base de données
  //     callback(new Error("my error message"));
  //
  // Une liste des modules Node.js pouvant être référencés est disponible ici :
  //
  //    https://tehsis.github.io/webtaskio-canirequire/
  const msg = 'Please implement the Login script for this database connection ' +
    'at https://manage.auth0.com/#/connections/database';
  return callback(new Error(msg));
}
```

<div id="aspnet-membership-provider-mvc3-universal-providers">
  ### ASP.NET Membership Provider (MVC3 - Universal Providers)
</div>

```javascript lines expandable theme={null}
function login(email, password, callback) {
  const crypto = require('crypto');
  const sqlserver = require('tedious@11.0.3');
  const Connection = sqlserver.Connection;
  const Request = sqlserver.Request;
  const TYPES = sqlserver.TYPES;
  const connection = new Connection({
    userName: 'the username',
    password: 'the password',
    server: 'the server',
    options: {
      database: 'the db name',
      encrypt: true // for Windows Azure
    }
  });
  /**
   * hashPassword
   *
   * This function creates a hashed version of the password to store in the database.
   *
   * @password  {[string]}      the password entered by the user
   * @return    {[string]}      the hashed password
   */
  function hashPassword(password, salt) {
    // the default implementation uses HMACSHA256 and since Key length is 64
    // and default salt is 16 bytes, Membership will fill the buffer repeating the salt
    const key = Buffer.concat([salt, salt, salt, salt]);
    const hmac = crypto.createHmac('sha256', key);
    hmac.update(Buffer.from(password, 'ucs2'));
    return hmac.digest('base64');
  }
  connection.on('debug', function(text) {
    // if you have connection issues, uncomment this to get more detailed info
    //console.log(text);
  }).on('errorMessage', function(text) {
    // this will show any errors when connecting to the SQL database or with the SQL statements
    console.log(JSON.stringify(text));
  });
  connection.on('connect', function(err) {
    if (err) return callback(err);
    getMembershipUser(email, function(err, user) {
      if (err || !user || !user.profile || !user.password) return callback(err || new WrongUsernameOrPasswordError(email));
      const salt = Buffer.from(user.password.salt, 'base64');
      if (hashPassword(password, salt).toString('base64') !== user.password.password) {
        return callback(new WrongUsernameOrPasswordError(email));
      }
      callback(null, user.profile);
    });
  });

  // Membership Provider implementation used on Microsoft.AspNet.Providers NuGet
  /**
   * getMembershipUser
   *
   * Cette fonction reçoit un nom d'utilisateur ou un courriel et retourne les informations
   * du fournisseur Membership de l'utilisateur, les hachages de mot de passe et le salt
   *
   * @usernameOrEmail  {[string]}       le nom d'utilisateur ou le courriel, la méthode effectuera une
   *                                    requête sur les deux avec un OR
   *
   * @callback         {[Function]}     le premier argument sera l'erreur le cas échéant,
   *                                    et le second argument sera un objet utilisateur
   */
  function getMembershipUser(usernameOrEmail, done) {
    var user = null;
    const query =
      'SELECT Memberships.UserId, Email, Users.UserName, Password ' +
      'FROM Memberships INNER JOIN Users ' +
      'ON Users.UserId = Memberships.UserId ' +
      'WHERE Memberships.Email = @Username OR Users.UserName = @Username';
    const getMembershipQuery = new Request(query, function(err, rowCount) {
      if (err || rowCount < 1) return done(err);
      done(err, user);
    });
    getMembershipQuery.addParameter('Username', TYPES.VarChar, usernameOrEmail);
    getMembershipQuery.on('row', function(fields) {
      user = {
        profile: {
          user_id: fields.UserId.value,
          nickname: fields.UserName.value,
          email: fields.Email.value,
        },
        password: {
          password: fields.Password.value,
          salt: fields.PasswordSalt.value
        }
      };
    });
    connection.execSql(getMembershipQuery);
  }
}
```

<div id="aspnet-membership-provider-mvc4-simple-membership">
  ### ASP.NET Membership Provider (MVC4 - Simple Membership)
</div>

```javascript lines expandable theme={null}
function login(email, password, callback) {
  const crypto = require('crypto');
  const sqlserver = require('tedious@11.0.3');
  const Connection = sqlserver.Connection;
  const Request = sqlserver.Request;
  const TYPES = sqlserver.TYPES;
  const connection = new Connection({
    userName: 'the username',
    password: 'the password',
    server: 'the server',
    options: {
      database: 'the db name',
      encrypt: true // for Windows Azure
    }
  });
  function fixedTimeComparison(a, b) {
    var mismatch = (a.length === b.length ? 0 : 1);
    if (mismatch) {
      b = a;
    }
    for (var i = 0, il = a.length; i < il; ++i) {
      const ac = a.charCodeAt(i);
      const bc = b.charCodeAt(i);
      mismatch += (ac === bc ? 0 : 1);
    }
    return (mismatch === 0);
  }

  /**
   * validatePassword
   *
   * Cette fonction récupère le mot de passe saisi par l'utilisateur, ainsi que le hachage
   * et le sel du mot de passe original provenant de la base de données, et effectue un hachage HMAC SHA256.
   *
   * @password      {[string]}      le mot de passe saisi par l'utilisateur
   * @originalHash  {[string]}      le hachage du mot de passe original provenant de la base de données
   *                                (incluant le sel).
   * @return        {[bool]}        true si le mot de passe est valide
   */
  function validatePassword(password, originalHash, callback) {
    const iterations = 1000;
    const hashBytes = Buffer.from(originalHash, 'base64');
    const salt = hashBytes.slice(1, 17);
    const hash = hashBytes.slice(17, 49);
    crypto.pbkdf2(password, salt, iterations, hash.length, 'sha1', function(err, hashed) {
      if (err) return callback(err);
      const hashedBase64 = Buffer.from(hashed, 'binary').toString('base64');
      const isValid = fixedTimeComparison(hash.toString('base64'), hashedBase64);
      return callback(null, isValid);
    });
  }

  connection.on('debug', function(text) {
    // if you have connection issues, uncomment this to get more detailed info
    //console.log(text);
  }).on('errorMessage', function(text) {
    // this will show any errors when connecting to the SQL database or with the SQL statements
    console.log(JSON.stringify(text));
  });
  connection.on('connect', function(err) {
    if (err) return callback(err);
    getMembershipUser(email, function(err, user) {
      if (err || !user || !user.profile) return callback(err || new WrongUsernameOrPasswordError(email));
      validatePassword(password, user.password, function(err, isValid) {
        if (err || !isValid) return callback(err || new WrongUsernameOrPasswordError(email));
        callback(null, user.profile);
      });
    });
  });

  // Membership Provider implementation used on Microsoft.AspNet.Providers NuGet
  /**
   * getMembershipUser
   *
   * This function gets a username or email and returns a user info, password hashes and salt
   *
   * @usernameOrEamil   {[string]}    the username or email, the method will do a query
   *                                  on both with an OR
   * @callback          {[Function]}  first argument will be the Error if any, and second
   *                                  argument will be a user object
   */
  function getMembershipUser(usernameOrEmail, done) {
    var user = null;
    const query =
      'SELECT webpages_Membership.UserId, UserName, UserProfile.UserName, Password from webpages_Membership ' +
      'INNER JOIN UserProfile ON UserProfile.UserId = webpages_Membership.UserId ' +
      'WHERE UserProfile.UserName = @Username';
    const getMembershipQuery = new Request(query, function(err, rowCount) {
      if (err || rowCount < 1) return done(err);
      done(err, user);
    });
    getMembershipQuery.addParameter('Username', TYPES.VarChar, usernameOrEmail);
    getMembershipQuery.on('row', function(fields) {
      user = {
        profile: {
          user_id: fields.UserId.value,
          nickname: fields.UserName.value,
          email: fields.UserName.value,
        },
        password: fields.Password.value
      };
    });
    connection.execSql(getMembershipQuery);
  }
}
```

<div id="mongodb">
  ### MongoDB
</div>

```javascript lines theme={null}
function login(email, password, callback) {
  const bcrypt = require('bcrypt');
  const MongoClient = require('mongodb@3.1.4').MongoClient;
  const client = new MongoClient('mongodb://user:pass@mymongoserver.com');
  client.connect(function (err) {
    if (err) return callback(err);
    const db = client.db('db-name');
    const users = db.collection('users');
    users.findOne({ email: email }, function (err, user) {
      if (err || !user) {
        client.close();
        return callback(err || new WrongUsernameOrPasswordError(email));
      }
      bcrypt.compare(password, user.password, function (err, isValid) {
        client.close();
        if (err || !isValid) return callback(err || new WrongUsernameOrPasswordError(email));
        return callback(null, {
            user_id: user._id.toString(),
            nickname: user.nickname,
            email: user.email
          });
      });
    });
  });
}
```

<div id="mysql">
  ### MySQL
</div>

```javascript lines theme={null}
function login(email, password, callback) {
  const mysql = require('mysql');
  const bcrypt = require('bcrypt');
  const connection = mysql({
    host: 'localhost',
    user: 'me',
    password: 'secret',
    database: 'mydb'
  });
  connection.connect();
  const query = 'SELECT id, nickname, email, password FROM users WHERE email = ?';
  connection.query(query, [ email ], function(err, results) {
    if (err) return callback(err);
    if (results.length === 0) return callback(new WrongUsernameOrPasswordError(email));
    const user = results[0];
    bcrypt.compare(password, user.password, function(err, isValid) {
      if (err || !isValid) return callback(err || new WrongUsernameOrPasswordError(email));
      callback(null, {
        user_id: user.id.toString(),
        nickname: user.nickname,
        email: user.email
      });
    });
  });
}
```

<div id="postgresql">
  ### PostgreSQL
</div>

```javascript lines expandable theme={null}
function login(email, password, callback) {
  //cet exemple utilise la bibliothèque "pg"
  //plus d'informations ici : https://github.com/brianc/node-postgres
  const bcrypt = require('bcrypt');
  const postgres = require('pg');
  const conString = 'postgres://user:pass@localhost/mydb';
  postgres.connect(conString, function (err, client, done) {
    if (err) return callback(err);
    const query = 'SELECT id, nickname, email, password FROM users WHERE email = $1';
    client.query(query, [email], function (err, result) {
      // REMARQUE : appelez toujours `done()` ici pour fermer
      // la connexion à la base de données
      done();
      if (err || result.rows.length === 0) return callback(err || new WrongUsernameOrPasswordError(email));
      const user = result.rows[0];
      bcrypt.compare(password, user.password, function (err, isValid) {
        if (err || !isValid) return callback(err || new WrongUsernameOrPasswordError(email));
        return callback(null, {
          user_id: user.id,
          nickname: user.nickname,
          email: user.email
        });
      });
    });
  });
}
```

<div id="sql-server">
  ### SQL Server
</div>

```javascript lines expandable theme={null}
function login(email, password, callback) {
  //cet exemple utilise la bibliothèque "tedious"
  //plus d'info ici : http://pekim.github.io/tedious/index.html
  const bcrypt = require('bcrypt');
  const sqlserver = require('tedious@11.0.3');
  const Connection = sqlserver.Connection;
  const Request = sqlserver.Request;
  const TYPES = sqlserver.TYPES;
  const connection = new Connection({
    userName:  'test',
    password:  'test',
    server:    'localhost',
    options:  {
      database: 'mydb',
      rowCollectionOnRequestCompletion: true
    }
  });
  const query = 'SELECT Id, Nickname, Email, Password FROM dbo.Users WHERE Email = @Email';
  connection.on('debug', function (text) {
    console.log(text);
  }).on('errorMessage', function (text) {
    console.log(JSON.stringify(text, null, 2));
  }).on('infoMessage', function (text) {
    console.log(JSON.stringify(text, null, 2));
  });
  connection.on('connect', function (err) {
    if (err) return callback(err);
    const request = new Request(query, function (err, rowCount, rows) {
      if (err || rowCount < 1) return callback(err || new WrongUsernameOrPasswordError(email));
      bcrypt.compare(password, rows[0][3].value, function (err, isValid) {
        if (err || !isValid) return callback(err || new WrongUsernameOrPasswordError(email));
        callback(null, {
          user_id: rows[0][0].value,
          nickname: rows[0][1].value,
          email: rows[0][2].value
        });
      });
    });
    request.addParameter('Email', TYPES.VarChar, email);
    connection.execSql(request);
  });
}
```

<div id="windows-azure-sql-database">
  ### Windows Azure SQL Database
</div>

```javascript lines expandable theme={null}
function login(email, password, callback) {
  //cet exemple utilise la bibliothèque "tedious"
  //plus d'informations ici : http://pekim.github.io/tedious/index.html
  var Connection = require('tedious@11.0.3').Connection;
  var Request = require('tedious@11.0.3').Request;
  var TYPES = require('tedious@11.0.3').TYPES;
  var bcrypt = require('bcrypt');
  var connection = new Connection({
    userName: 'your-user@your-server-id.database.windows.net',
    password: 'the-password',
    server: 'your-server-id.database.windows.net',
    options: {
      database: 'mydb',
      encrypt: true,
      rowCollectionOnRequestCompletion: true
    }
  });
  var query = "SELECT Id, Email, Password " +
    "FROM dbo.Users WHERE Email = @Email";
  connection.on('debug', function (text) {
    // Décommentez la ligne suivante pour activer les messages de débogage
    // console.log(text);
  }).on('errorMessage', function (text) {
    console.log(JSON.stringify(text, null, 2));
    return callback(text);
  }).on('infoMessage', function (text) {
    // Décommentez la ligne suivante pour activer les messages d'information
    // console.log(JSON.stringify(text, null, 2));
  });
  connection.on('connect', function (err) {
    if (err) { return callback(err); }
    var request = new Request(query, function (err, rowCount, rows) {
      if (err) {
        callback(new Error(err));
      } else if (rowCount < 1) {
        callback(new WrongUsernameOrPasswordError(email));
      } else {
        bcrypt.compare(password, rows[0][2].value, function (err, isValid) {
          if (err) { callback(new Error(err)); }
          else if (!isValid) { callback(new WrongUsernameOrPasswordError(email)); }
          else {
            callback(null, {
              user_id: rows[0][0].value,
              email: rows[0][1].value
            });
          }
        });
      }
    });
    request.addParameter('Email', TYPES.VarChar, email);
    connection.execSql(request);
  });
}
```

<div id="axios">
  ### Axios
</div>

```js lines expandable theme={null}
async function loginAsync(email, password, callback) {
  //à mettre à jour lorsque de nouvelles versions d'axios sont disponibles (https://auth0-extensions.github.io/canirequire/#axios)
  const axios = require("axios@0.22.0");

  let response;

  try {
    response = await axios.post(
      //stocker l'URL de l'API dans les paramètres de connexion pour mieux prendre en charge les environnements SDLC
      configuration.baseAPIUrl + "/login",
      //identifiants de l'utilisateur transmis dans le corps de la requête
      {
        email: email,
        password: password,
      },
      {
        timeout: 10000, //terminer l'appel proprement si la requête expire afin que le script puisse effectuer le rappel nécessaire
        headers: {
          //sécurisation de l'appel API avec l'apiKey stockée dans les paramètres de connexion.
          //approche simple et rapide, mais l'utilisation de jetons M2M est plus sécurisée car
          // un secret ne doit pas être partagé entre l'application et l'API.
          "x-api-key": configuration.apiKey,
        },
      }
    );
  } catch (e) {
    if (e.response.status === 404) {
      //supposant que l'API retourne 404 lorsque le courriel/nom d'utilisateur/mot de passe est invalide
      return callback(
        new WrongUsernameOrPasswordError(email, "Invalid credentials provided.")
      );
    }
    //rappel pour tout autre type d'erreur
    return callback(new Error(e.message));
  }

  try {
    let user = response.data;

    //si vous utilisez plusieurs connexions de base de données personnalisées dans votre locataire, préfixez
    //l'user_id avec une clé propre à la connexion, ex. : "connName|" + user.user_id
    //cela garantit des identifiants d'utilisateur uniques pour toutes les connexions de base de données
    return callback(null, {
      user_id: user.user_id,
      email: user.email,
    });
  } catch (e) {
    return callback(new Error(e.message));
  }
}
```

<div id="stormpath">
  ### Stormpath
</div>

```javascript lines expandable theme={null}
function login(username, password, callback) {
  // Remplacez {yourStormpathClientId} par votre ID Stormpath
  var url = 'https://api.stormpath.com/v1/applications/{yourStormpathClientId}/loginAttempts';
  // Ajoutez votre ID client et votre secret d'API Stormpath
  var apiCredentials = {
    user : '{yourStormpathApiId}',
    password: '{yourStormpathApiSecret}'
  };
  // Stormpath exige que les informations d'identification de l'utilisateur soient transmises sous forme de message encodé en base64
  var credentials = Buffer.from(username + ':' + password).toString('base64');
  // Effectuez une requête POST pour authentifier un utilisateur
  request({
    url: url,
    method: 'POST',
    auth: apiCredentials,
    json: {
      type: 'basic',
      // Transmission des informations d'identification encodées en base64
      value: credentials
    }
  }, function (error, response, body) {
    // Si la réponse est réussie, on continue
    if (response.statusCode !== 200) return callback();
    // Une réponse réussie retourne une URL pour récupérer les informations de l'utilisateur
    var accountUrl = body.account.href;
    // Effectuez une deuxième requête pour récupérer les informations de l'utilisateur.
    request({
      url: accountUrl,
      auth: apiCredentials,
      json: true
    }, function (errorUserInfo, responseUserInfo, bodyUserInfo) {
      // Si la réponse est réussie, on la traite
      if (responseUserInfo.statusCode !== 200) return callback();
      // Pour obtenir l'identifiant de l'utilisateur, on retire l'URL de l'API Stormpath
      var id = bodyUserInfo.href.replace('https://api.stormpath.com/v1/accounts/', '');
      // Enfin, on définit les données à stocker dans Auth0 et on migre l'utilisateur
      return callback(null, {
        user_id : id,
        username: bodyUserInfo.username,
        email: bodyUserInfo.email,
        // On définit email_verified à true en supposant que si l'utilisateur était valide
        // dans Stormpath, il a déjà vérifié son courriel
        // Si ce champ n'est pas défini, l'utilisateur recevra un courriel lui demandant de vérifier
        // son compte. Vous pouvez décider comment gérer cela selon votre cas d'utilisation
        email_verified: true
        // Ajoutez tout champ supplémentaire que vous souhaitez transférer depuis Stormpath
      });
    });
  });
}
```

<div id="learn-more">
  ## Pour en savoir plus
</div>

* [Modèles de scripts pour changer le mot de passe](/fr-CA/docs/authenticate/database-connections/custom-db/templates/change-password)
* [Modèles de scripts pour la création](/fr-CA/docs/authenticate/database-connections/custom-db/templates/create)
* [Modèles de scripts pour la suppression](/fr-CA/docs/authenticate/database-connections/custom-db/templates/delete)
* [Modèles de scripts pour récupérer un utilisateur](/fr-CA/docs/authenticate/database-connections/custom-db/templates/get-user)
* [Modèles de scripts pour la vérification](/fr-CA/docs/authenticate/database-connections/custom-db/templates/verify)
* [Modèle de script pour changer le courriel](/fr-CA/docs/authenticate/database-connections/custom-db/templates/change-email)
