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

# 作成スクリプトのテンプレート

> ユーザーを作成するための、カスタムデータベースのアクションスクリプト用テンプレートについて説明します。

作成スクリプトは、ユーザーが作成されるときに定義された関数を実装します。この関数の名前は`create`にすることをお勧めします。

これは任意のスクリプトです。これが有効になっている場合は、ユーザーがユニバーサルログイン経由でサインアップするとき、またはユーザーが<Tooltip data-tooltip-id="react-containers-DefinitionTooltip-0" href="/docs/ja-jp/glossary?term=auth0-dashboard" tip="Auth0 Dashboard: サービスを構成するためのAuth0の主製品。" cta="用語集の表示">Auth0 Dashboard</Tooltip>またはAuth0 <Tooltip data-tooltip-id="react-containers-DefinitionTooltip-0" href="/docs/ja-jp/glossary?term=management-api" tip="Management API: 顧客が管理タスクを実行できるようにするための製品。" cta="用語集の表示">Management API</Tooltip>で作成されるときに、Auth0がこのスクリプトを実行し、対応するユーザーレコードを外部データベースに作成します。

ユーザーがAuth0で作成されるときは、Auth0が一連のスクリプトを呼び出します。

1. [ユーザー取得](/docs/ja-jp/authenticate/database-connections/custom-db/templates/get-user)：ユーザーがまだAuth0や外部データベースに存在しないことを確認する。
2. 作成：ユーザーを外部データベースに作成する。
3. [ログイン](/docs/ja-jp/authenticate/database-connections/custom-db/templates/login)：ユーザーが正常に作成されたことを確認する。

## 作成関数

`create`関数は以下を行います。

* ユーザーのプロファイルデータを外部データベースのAPIに送信する。
* ユーザー作成の操作に失敗した場合には、エラーを返す。

### 定義

`create`関数は2つのパラメーターを受け取り、`callback`関数を返します。

```js lines theme={null}
create(user, callback): function
```

| パラメーター     | タイプ    | 説明                                                             |
| ---------- | ------ | -------------------------------------------------------------- |
| `user`     | オブジェクト | ユーザー作成プロセスから取得した[ユーザープロファイルデータ](#user-object-parameter)が含まれます。 |
| `callback` | 関数     | パイプラインを通してエラーデータを渡すために使用されます。                                  |

### 例

これは疑似JavaScriptを使った例で、どのようにすれば`create`関数を実装できるかがわかります。言語固有の例については、「[言語固有のスクリプトの例](#language-specific-script-examples)」をお読みください。

```javascript lines expandable theme={null}
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);
  });
}
```

### Encryption（暗号化）

<Warning>
  パスワード資格情報を非暗号化形式でログ、保存、または送受信してはいけません。
</Warning>

`bcrypt`のような暗号学的ハッシュの暗号化ライブラリを使ってパスワード値を暗号化し、潜在的なデータ漏洩を防ぎます。

#### 例

```js lines theme={null}
bcrypt.hash(password, 10, function (err, hash) {
    if (err) {
        return callback(err);
    } else {
        // Return hashed password
    }
});
```

## コールバック関数

`callback`関数は1つのパラメーターを受け取り、1つの関数を返します。

### 定義

```js lines theme={null}
callback(error): function
```

| パラメーター  | タイプ    | 必須 | 説明         |
| ------- | ------ | -- | ---------- |
| `error` | オブジェクト | 必須 | エラーデータを含む。 |

### 成功の場合

ユーザー作成操作が成功した場合、`callback`関数を返し、`error`パラメーターには`null`値を渡します。

#### 例

```js lines theme={null}
return callback(null);
```

### エラーの場合

エラーが発生した場合は、コールバック関数を返し、`error`パラメーターに関連するエラー情報を渡します。

#### ValidationErrorタイプのオブジェクト

`ValidationError`のカスタムエラータイプのオブジェクトを使うと、[テナントログ](/docs/ja-jp/deploy-monitor/logs)で表示されるデータを渡すことができます。

##### コンストラクター

`ValidationError`コンストラクターは、最大2つのパラメーターを受け取ります。

```js lines theme={null}
new ValidationError(errorCode[, message]): ValidationError
```

| パラメーター      | 説明                     |
| ----------- | ---------------------- |
| `errorCode` | （必須）文字列。エラーのタイプを指定します。 |
| `message`   | （任意）文字列。エラーに関する情報を含む。  |

#### ユーザーがすでに存在するというエラーを返す

`errorCode`パラメーターの値に`user_exists`を指定してエラーを返すと、Auth0は`fs`のテナントログイベントを記録します。

##### 例

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

| テナントのログイベントのフィールド   | 値                          |
| ------------------- | -------------------------- |
| **Code（コード）**       | `fs`                       |
| **Event（イベント）**     | Failed Signup              |
| **Description（説明）** | `My custom error message.` |

## ユーザーオブジェクトパラメーター

`user`オブジェクトパラメーターには、ユーザー作成プロセスから取得した事前定義された一連のプロパティが含まれます。

| プロパティ           | 説明                                                                                                                                |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `client_id`     | ユニバーサルログインを通してユーザーがサインアップした場合は、Auth0アプリケーションのクライアントIDです。Auth0 DashboardまたはManagement APIを通してユーザーが作成された場合は、APIキーです。                |
| `tenant`        | Auth0テナント名です。                                                                                                                     |
| `email`         | ユーザーのメールアドレスです。                                                                                                                   |
| `password`      | テキスト形式で表記したユーザーのパスワードです。                                                                                                          |
| `username`      | ユーザーのユーザー名です。カスタムデータベース接続の[**［Requires Username（ユーザー名を要求する）］**](/docs/ja-jp/connections/database/require-username)設定が有効の場合は、必須です。 |
| `connection`    | Auth0接続名です。                                                                                                                       |
| `user_metadata` | オブジェクトが存在する場合は、ユーザーのAuth0プロファイルにある`user_metadata`オブジェクトのプロパティを含みます。                                                               |
| `app_metadata`  | オブジェクトが存在する場合は、ユーザーのAuth0プロファイルにある`app_metadata`オブジェクトのプロパティを含みます。                                                                |

### ユーザー名プロパティ

カスタムデータベース接続の[［Requires Username（ユーザー名を要求する）］](/docs/ja-jp/authenticate/database-connections/require-username)設定が有効になっている場合は、[ログイン](/docs/ja-jp/authenticate/database-connections/custom-db/templates/login)および[ユーザー取得](/docs/ja-jp/authenticate/database-connections/custom-db/templates/get-user)スクリプトが`username`プロパティをサポートする必要があるため、ユーザー名プロパティを外部データベースに保存しなければなりません。

### ユーザーメタデータとアプリメタデータ

`user_metadata`と`app_metadata`のプロパティは、外部データベースに保存する必要はありません。これらの値は、内部で作成されるユーザープロファイルレコードの一部として自動保存されます。

### カスタムサインアップフィールド

サインアップのプロセス中に[カスタムフィールドを作成して使用](/docs/ja-jp/libraries/custom-signup#using-the-api)する場合、これらは`user`オブジェクトに含まれます。

### 例

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

## 言語固有のスクリプトの例

Auth0は、以下の言語や技術で使用できるサンプルスクリプトを提供しています。

* [JavaScript](#javascript)
* [ASP.NET Membership Provider（MVC3 - Universal Providers）](#asp-net-membership-provider-mvc3-universal-providers-)
* [ASP.NET Membership Provider（MVC4 - Universal Providers）](#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)
* [Basic認証での要求](#request-with-basic-auth)

### JavaScript

```javascript lines expandable theme={null}
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));
}
```

### ASP.NET Membership Provider（MVC3 - Universal Providers）

```javascript lines expandable theme={null}
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);
  }
}
```

### ASP.NET Membership Provider（MVC4 - Simple Membership）

```javascript lines expandable theme={null}
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);
  });
}
```

### MongoDB

```javascript lines expandable theme={null}
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);
        });
      });
    });
  });
}
```

### MySQL

```javascript lines theme={null}
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);
    });
  });
}
```

### PostgreSQL

```javascript lines theme={null}
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);
      });
    });
  });
}
```

### SQL Server

```javascript lines expandable theme={null}
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);
    });
  });
}
```

### Windows Azure SQL Database

```javascript lines expandable theme={null}
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);
    });
  });
}
```

### Basic認証での要求

```javascript lines theme={null}
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);
  });
}
```

## トラブルシューティング

レガシーデータベースかAuth0のいずれかでユーザーを作成できない場合は、以下を行います。

1. Auth0の[Actions リアルタイムログ](/docs/ja-jp/customize/actions/actions-real-time-logs)で`console.log()`のステートメントを確認します。
2. レガシーデータベースでユーザーを探し、適宜削除します。ユーザーの状態の一部がAuth0にある場合は、Management APIの[ユーザー削除](https://auth0.com/docs/api/management/v2#!/Users/delete_users_by_id)エンドポイントまたは[接続ユーザー削除](/docs/ja-jp/api/management/v2#!/Connections/delete_users_by_email)エンドポイントを使用します。
3. **［Import Mode（インポートモード）］** が無効になっていることを確認してから、作成スクリプトを構成します。

## もっと詳しく

* [ログインスクリプトのテンプレート](/docs/ja-jp/authenticate/database-connections/custom-db/templates/login)
* [ユーザー取得スクリプトのテンプレート](/docs/ja-jp/authenticate/database-connections/custom-db/templates/get-user)
* [スクリプトのテンプレートを削除する](/docs/ja-jp/authenticate/database-connections/custom-db/templates/delete)
* [検証スクリプトのテンプレート](/docs/ja-jp/authenticate/database-connections/custom-db/templates/verify)
* [パスワード変更スクリプトのテンプレート](/docs/ja-jp/authenticate/database-connections/custom-db/templates/change-password)
* [メール変更スクリプトのテンプレート](/docs/ja-jp/authenticate/database-connections/custom-db/templates/change-email)
