Créer des modèles de script

Le script Créer implémente la fonction définie lors de la création d’un utilisateur. Nous recommandons de nommer cette fonction create.

Ce script est facultatif. Si cette option est activée, lorsqu’un utilisateur s’inscrit via la connexion universelle ou est créé via Auth0 Dashboard ou Management API Auth0, Auth0 exécutera le script pour créer un enregistrement utilisateur correspondant dans la base de données externe.

Lorsqu’un utilisateur est créé dans Auth0, Auth0 appelle une série de scripts :

  1. Obtenir utilisateur : vérifie que l’utilisateur n’existe pas déjà dans Auth0 ou dans la base de données externe.

  2. Créer : permet de créer l’utilisateur de la base de données externe.

  3. Connexion : vérifie que l’utilisateur a été créé avec succès.

Fonction Créer

La fonction Create permet de :

  • envoyer les profil de l’utilisateur des données à l’API de la base de données externe.

  • renvoyer une erreur si la création de l’utilisateur échoue.

Définition

La fonction create accepte deux paramètres et renvoie une fonction de callback :

create(user, callback): function

Was this helpful?

/

Paramètre Type Description
user Objet Contient les données de profil utilisateur tirées du processus de création de l’utilisateur.
callback Fonction Utilisée pour transmettre les données d’erreur dans le pipeline.

Exemple

Voici un exemple fictif en JavaScript de la manière dont vous pourriez implémenter la fonction create. Pour des exemples spécifiques à un langage, consultez Exemples de scripts spécifiques à un langage.

function create(user, callback) {
  // Send user profile data to external database API
  let hashedPassword = hash(user.password);

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

  send(options, err => {
    // Return error in callback if user already exists
    if (err && err.id === "USER_ALREADY_EXISTS") {
      return callback(new ValidationError("user_exists", "My custom error message."));
    } else if (err) {
      // Return error in callback if error occurred
      return callback(new Error("My custom error message."));
    }

    // Return `null` value in callback if user creation operation succeeded
    return callback(null);
  });
}

Was this helpful?

/

Chiffrement

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

Exemple

bcrypt.hash(password, 10, function (err, hash) {
    if (err) {
        return callback(err);
    } else {
        // Return hashed password
    }
});

Was this helpful?

/

Fonction de rappel

La fonction de callback accepte un paramètre et renvoie une fonction.

Définition

callback(error): function

Was this helpful?

/

Paramètre Type Requis Description
error Objet Requis Contient des données d’erreur.

Retourne un succès

Si l’opération de création de l’utilisateur a réussi, renvoyez la fonction de callback et passer une valeur null comme paramètre error paramètre.

Exemple

return callback(null);

Was this helpful?

/

Renvoyer une erreur

Si une erreur survient, renvoyez la fonction de rappel, et transmettez l’information pertinente concernant l’erreur au paramètre error :

Objet de type ValidationError

L’objet de type erreur personnalisé ValidationError vous permet de transmettre des données qui seront affichées dans vos Journaux du locataire.

Constructeur

Le constructeur ValidationError accepte jusqu’à deux paramètres :

new ValidationError(errorCode[, message]): ValidationError

Was this helpful?

/

Paramètre Description
errorCode (Requis) Chaîne. Indique le type d’erreur.
message (Facultatif) Chaîne. Contient des informations sur l’erreur.

Renvoie une erreur indiquant que l’utilisateur existe déjà

Si vous renvoyez une erreur avec la valeur user_exists pour le paramètre errorCode, Auth0 enregistrera un événement du journal du locataire fs.

Exemple

return callback(new ValidationError("user_exists", "My custom error message."));

Was this helpful?

/

Champ Événement de journal des locataires Valeur
Code fs
Événement Échec d’inscription
Description My custom error message.

Paramètre d’objet utilisateur

Le paramètre d’objet user contient un ensemble prédéfini de propriétés provenant du processus de création de l’utilisateur :

Propriété Description
client_id L’ID client de l’application Auth0 si l’utilisateur s’est inscrit par la connexion universelle, ou la clé API si l’utilisateur a été créé par l’Auth0 Dashboard ou par Management API.
tenant Le nom du locataire Auth0.
email L’adresse courriel de l’utilisateur.
password Le mot de passe de l’utilisateur en texte brut.
username Le nom d’utilisateur de l’utilisateur. Requis uniquement si le paramètre Nécessite le nom d’utilisateur est activé pour la connexion à la base de données personnalisée.
connection Le nom de la connexion Auth0.
user_metadata Contient les propriétés de l’objet user_metadata sur le profil Auth0 de l’utilisateur, si l’objet existe.
app_metadata Contient les propriétés de l’objet app_metadata sur le profil Auth0 de l’utilisateur, si l’objet existe.

Propriété du nom d’utilisateur

Si votre connexion à la base de données personnalisée a le paramètre Requires Username activé, alors les scripts Login et Get User doivent prendre en charge la propriété username, vous devez donc la stocker dans votre base de données externe.

Métadonnées de l’utilisateur et de l’application

Les propriétés user_metadata et app_metadata n’ont pas besoin d’être stockées dans votre base de données externe. Auth0 stocke automatiquement ces valeurs dans le cadre de l’enregistrement de profil utilisateur créé en interne.

Champs d’inscription personnalisés

Si vous créez et utilisez des champs personnalisés pendant le processus d’inscription, ils seront inclus dans l’objet user.

Exemple

{
    client_id: "8tkMo6n1QkKOazqPcSQd8wU7LzXYibgK",
    tenant: "{yourAuth0Tenant}",
    email: "username@domain.com",
    password: "mySuperSecretPassword123",
    username: "username456",
    user_metadata: {
        "language": "en"
    },
    app_metadata: {
        "plan": "full"
    }
}

Was this helpful?

/

Exemples de scripts propres à une langue

Auth0 fournit des exemples de scripts à utiliser avec les langages/technologies ci-dessous :

JavaScript

function create(user, callback) {
  // This script should create a user entry in your existing database. It will
  // be executed when a user attempts to sign up, or when a user is created
  // through the Auth0 Dashboard or Management API.
  // When this script has finished executing, the Login script will be
  // executed immediately afterwards, to verify that the user was created
  // successfully.
  //
  // The user object will always contain the following properties:
  // * email: the user's email
  // * password: the password entered by the user, in plain text
  // * tenant: the name of this Auth0 account
  // * client_id: the client ID of the application where the user signed up, or
  //              API key if created through the Management API or Auth0 Dashboard
  // * connection: the name of this database connection
  //
  // There are three ways this script can finish:
  // 1. A user was successfully created
  //     callback(null);
  // 2. This user already exists in your database
  //     callback(new ValidationError("user_exists", "my error message"));
  // 3. Something went wrong while trying to reach your database
  //     callback(new Error("my error message"));
  const msg = 'Please implement the Create script for this database connection ' +
    'at https://manage.auth0.com/#/connections/database';
  return callback(new Error(msg));
}

Was this helpful?

/

Fournisseur d’appartenances ASP.NET (MVC3 – Fournisseurs universels)

function create(user, callback) {
  const crypto = require('crypto');
  const sqlserver = require('tedious@1.11.0');
  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,
      // Required to retrieve userId needed for Membership entity creation
      rowCollectionOnRequestCompletion: true
    }
  });
  const applicationId = 'your-application-id-goes-here';
  /**
   * 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);
    }
    createMembershipUser(user, function(err, user) {
      if (err) return callback(err); // this will return a 500
      if (!user) return callback(); // this will return a 401
      callback(null, user);
    });
  });
  function createMembershipUser(user, callback) {
    const userData = {
      UserName: user.email,
      ApplicationId: applicationId
    };
    const createUser =
      'INSERT INTO Users (UserName, LastActivityDate, ApplicationId, UserId, IsAnonymous) ' +
      'OUTPUT Inserted.UserId ' +
      'VALUES (@UserName, GETDATE(), @ApplicationId, NEWID(), \'false\')';
    const createUserQuery = new Request(createUser, function(err, rowCount, rows) {
      if (err) return callback(err);
      // No records added
      if (rowCount === 0) return callback(null);
      const userId = rows[0][0].value;
      const salt = crypto.randomBytes(16);
      const membershipData = {
        ApplicationId: applicationId,
        Email: user.email,
        Password: hashPassword(user.password, salt),
        PasswordSalt: salt.toString('base64'),
        UserId: userId
      };
      const createMembership =
        'INSERT INTO Memberships (ApplicationId, UserId, Password, PasswordFormat, ' +
        'PasswordSalt, Email, isApproved, isLockedOut, CreateDate, LastLoginDate, ' +
        'LastPasswordChangedDate, LastLockoutDate, FailedPasswordAttemptCount, ' +
        'FailedPasswordAttemptWindowStart, FailedPasswordAnswerAttemptCount, ' +
        'FailedPasswordAnswerAttemptWindowsStart) ' +
        'VALUES ' +
        '(@ApplicationId, @UserId, @Password, 1, @PasswordSalt, ' +
        '@Email, \'false\', \'false\', GETDATE(), GETDATE(), GETDATE(), GETDATE(), 0, 0, 0, 0)';
      const createMembershipQuery = new Request(createMembership, function(err, rowCount) {
        if (err) return callback(err);
        if (rowCount === 0) return callback(null);
        callback(null, rowCount > 0);
      });
      createMembershipQuery.addParameter('ApplicationId', TYPES.VarChar, membershipData.ApplicationId);
      createMembershipQuery.addParameter('Email', TYPES.VarChar, membershipData.Email);
      createMembershipQuery.addParameter('Password', TYPES.VarChar, membershipData.Password);
      createMembershipQuery.addParameter('PasswordSalt', TYPES.VarChar, membershipData.PasswordSalt);
      createMembershipQuery.addParameter('UserId', TYPES.VarChar, membershipData.UserId);
      connection.execSql(createMembershipQuery);
    });
    createUserQuery.addParameter('UserName', TYPES.VarChar, userData.UserName);
    createUserQuery.addParameter('ApplicationId', TYPES.VarChar, userData.ApplicationId);
    connection.execSql(createUserQuery);
  }
}

Was this helpful?

/

Fournisseur d’appartenances ASP.NET (MVC4 – Appartenance simple)

function create(user, callback) {
  const crypto = require('crypto');
  const sqlserver = require('tedious@1.11.0');
  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,
      // Required to retrieve userId needed for Membership entity creation
      rowCollectionOnRequestCompletion: true
    }
  });
  /**
   * hashPassword
   *
   * This function hashes a password using HMAC SHA256 algorithm.
   *
   * @password    {[string]}    password to be hased
   * @salt        {[string]}    salt to be used in the hashing process
   * @callback    {[function]}  callback to be called after hashing the password
   */
  function hashPassword(password, salt, callback) {
    const iterations = 1000;
    const passwordHashLength = 32;
    crypto.pbkdf2(password, salt, iterations, passwordHashLength, 'sha1', function (err, hashed) {
      if (err) return callback(err);
      const result = Buffer.concat([Buffer.from([0], 1), salt, Buffer.from(hashed, 'binary')]);
      const resultBase64 = result.toString('base64');
      callback(null, resultBase64);
    });
  }
  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);
    const createUser =
      'INSERT INTO UserProfile (UserName) ' +
      'OUTPUT Inserted.UserId ' +
      'VALUES (@UserName)';
    const createUserQuery = new Request(createUser, function (err, rowCount, rows) {
      if (err || rowCount === 0) return callback(err);
      const userId = rows[0][0].value;
      const salt = crypto.randomBytes(16);
      const createMembership =
        'INSERT INTO webpages_Membership ' +
        '(UserId, CreateDate, IsConfirmed, PasswordFailuresSinceLastSuccess, Password, PasswordSalt) ' +
        'VALUES ' +
        '(@UserId, GETDATE(), \'false\', 0, @Password, \'\')';
      const createMembershipQuery = new Request(createMembership, function (err, rowCount) {
        if (err || rowCount === 0) return callback(err);
        callback(null, rowCount > 0);
      });
      hashPassword(user.password, salt, function (err, hashedPassword) {
        if (err) return callback(err);
        createMembershipQuery.addParameter('Password', TYPES.VarChar, hashedPassword);
        createMembershipQuery.addParameter('PasswordSalt', TYPES.VarChar, salt.toString('base64'));
        createMembershipQuery.addParameter('UserId', TYPES.VarChar, userId);
        connection.execSql(createMembershipQuery);
      });
    });
    createUserQuery.addParameter('UserName', TYPES.VarChar, user.email);
    connection.execSql(createUserQuery);
  });
}

Was this helpful?

/

MongoDB

function create(user, 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: user.email }, function (err, withSameMail) {
      if (err || withSameMail) {
        client.close();
        return callback(err || new Error('the user already exists'));
      }
      bcrypt.hash(user.password, 10, function (err, hash) {
        if (err) {
          client.close();
          return callback(err);
        }
        user.password = hash;
        users.insert(user, function (err, inserted) {
          client.close();
          if (err) return callback(err);
          callback(null);
        });
      });
    });
  });
}

Was this helpful?

/

MySQL

function create(user, callback) {
  const mysql = require('mysql');
  const bcrypt = require('bcrypt');
  const connection = mysql({
    host: 'localhost',
    user: 'me',
    password: 'secret',
    database: 'mydb'
  });
  connection.connect();
  const query = 'INSERT INTO users SET ?';
  bcrypt.hash(user.password, 10, function(err, hash) {
    if (err) return callback(err);
    const insert = {
      password: hash,
      email: user.email
    };
    connection.query(query, insert, function(err, results) {
      if (err) return callback(err);
      if (results.length === 0) return callback();
      callback(null);
    });
  });
}

Was this helpful?

/

PostgreSQL

function create(user, callback) {
  //this example uses the "pg" library
  //more info here: 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);
    bcrypt.hash(user.password, 10, function (err, hashedPassword) {
      if (err) return callback(err);
      const query = 'INSERT INTO users(email, password) VALUES ($1, $2)';
      client.query(query, [user.email, hashedPassword], function (err, result) {
        // NOTE: always call `done()` here to close
        // the connection to the database
        done();
        return callback(err);
      });
    });
  });
}

Was this helpful?

/

SQL Server

function create(user, callback) {
  //this example uses the "tedious" library
  //more info here: http://pekim.github.io/tedious/index.html
  const bcrypt = require('bcrypt');
  const sqlserver = require('tedious@1.11.0');
  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'
    }
  });
  const query = 'INSERT INTO dbo.Users SET Email = @Email, Password = @Password';
  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, rows) {
      if (err) return callback(err);
      callback(null);
    });
    bcrypt.hash(user.password, 10, function(err, hash) {
      if (err) return callback(err);
      request.addParameter('Email', TYPES.VarChar, user.email);
      request.addParameter('Password', TYPES.VarChar, hash);
      connection.execSql(request);
    });
  });
}

Was this helpful?

/

Base de données SQL de Windows Azure

function create (user, callback) {
  //this example uses the "tedious" library
  //more info here: http://pekim.github.io/tedious/index.html
  var Connection = require('tedious@1.11.0').Connection;
  var Request = require('tedious@1.11.0').Request;
  var TYPES = require('tedious@1.11.0').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
    }
  });
  var query = "INSERT INTO users (Email, Password) VALUES (@Email, @Password)";
  connection.on('debug', function(text) {
    // Uncomment next line in order to enable debugging messages
    // console.log(text);
  }).on('errorMessage', function(text) {
    console.log(JSON.stringify(text, null, 2));
  }).on('infoMessage', function(text) {
    // Uncomment next line in order to enable information messages
    // console.log(JSON.stringify(text, null, 2));
  });
  connection.on('connect', function (err) {
    if (err) { return callback(err); }
    var request = new Request(query, function (err, rows) {
      if (err) { return callback(err); }
      console.log('rows: ' + rows);
      callback(null);
    });
    bcrypt.hash(user.password, 10, function (err, hashedPassword) {
      if (err) { return callback(err); }
      request.addParameter('Email', TYPES.VarChar, user.email);
      request.addParameter('Password', TYPES.VarChar, hashedPassword);
      connection.execSql(request);
    });
  });
}

Was this helpful?

/

Demande avec Basic Auth

function create(user, callback) {
  const request = require('request');
  request.post({
    url: 'https://myserviceurl.com/users',
    json: user
    //for more options check:
    //https://github.com/mikeal/request#requestoptions-callback
  }, function(err, response, body) {
    if (err) return callback(err);
    callback(null);
  });
}

Was this helpful?

/

Dépanner

Si vous ne parvenez pas à créer un utilisateur dans votre base de données héritée ou dans Auth0 :

  1. Vérifiez les instructions console.log() avec l’extension des journaux WebTask en temps réel d’Auth0.

  2. Recherchez l’utilisateur dans votre base de données héritée et supprimez-le. Si l’état utilisateur partiel est dans Auth0, utilisez les points de terminaison Supprimer un utilisateur ou Supprimer un utilisateur de connexion du Management API.

  3. Assurez-vous que le Mode d’importation est désactivé, puis configurez le script de création.

En savoir plus