> ## 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.

# ユーザー作成データベースアクションスクリプトとテンプレート

> Create スクリプトは、ユーザーが Universal Login からサインアップしたとき、または Auth0 Dashboard か Management API を通じてユーザーを作成したときに実行されます。

Create スクリプトでは、ユーザー作成時に呼び出される定義済み関数を実装します。この関数名は `create` にすることを推奨します。

このスクリプトは任意です。有効にすると、ユーザーが <Tooltip tip="Universal Login: ユーザーのアイデンティティを確認するために、アプリケーションは Auth0 の認可サーバーでホストされている Universal Login にリダイレクトされます。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=Universal+Login">Universal Login</Tooltip> からサインアップした場合、または <Tooltip tip="Auth0 Dashboard: サービスを構成するための Auth0 の主要製品です。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=Auth0+Dashboard">Auth0 Dashboard</Tooltip> か Auth0 <Tooltip tip="Auth0 Dashboard: サービスを構成するための Auth0 の主要製品です。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=Management+API">Management API</Tooltip> を通じて作成された場合に、Auth0 は外部データベース内に対応するユーザーレコードを作成するため、このスクリプトを実行します。

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

1. [Get User](/docs/ja-jp/authenticate/database-connections/custom-db/templates/get-user): ユーザーが Auth0 または外部データベースにまだ存在しないことを確認します。
2. Create: 外部データベースにユーザーを作成します。
3. [Login](/docs/ja-jp/authenticate/database-connections/custom-db/templates/login): ユーザーが正常に作成されたことを確認します。

<div id="create-function">
  ## Create 関数
</div>

`create` 関数では、次の処理を行う必要があります。

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

<div id="definition">
  ### 定義
</div>

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

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

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

これは、`create` 関数の実装方法を示す擬似的なJavaScriptの例です。

```javascript lines expandable theme={null}
function create(user, callback) {
  // ユーザープロファイルデータを外部データベース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 => {
    // ユーザーがすでに存在する場合はコールバックでエラーを返す
    if (err && err.id === "USER_ALREADY_EXISTS") {
      return callback(new ValidationError("user_exists", "My custom error message."));
    } else if (err) {
      // エラーが発生した場合はコールバックでエラーを返す
      return callback(new Error("My custom error message."));
    }

    // ユーザー作成が成功した場合はコールバックで`null`を返す
    return callback(null);
  });
}
```

<div id="encryption">
  ### 暗号化
</div>

データ漏洩のリスクを防ぐため、`bcrypt` などの暗号学的ハッシュライブラリを使用してパスワード値をハッシュ化します。暗号化されていないパスワード認証情報をログに記録、保存、転送しないでください。

例:

```js theme={null}
bcrypt.hash(password, 10, function (err, hash) {
    if (err) {
        return callback(err);
    } else {
        // ハッシュ化されたパスワードを返す
    }
});
```

<div id="callback-function">
  ## コールバック関数
</div>

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

<div id="definition">
  ### 定義
</div>

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

| パラメータ   | 型      | 必須 | 説明          |
| ------- | ------ | -- | ----------- |
| `error` | オブジェクト | 必須 | エラー情報を含みます。 |

<div id="validationerror-type-object">
  ### ValidationError 型オブジェクト
</div>

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

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

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

| パラメータ       | 説明                           |
| ----------- | ---------------------------- |
| `errorCode` | (必須) String。エラーの種類を指定します。    |
| `message`   | (任意) String。エラーに関する情報が含まれます。 |

<div id="return-a-success">
  ### 成功を返す
</div>

ユーザー作成処理が成功した場合は、コールバック関数を呼び出し、`error` パラメータに `null` を渡します：

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

<div id="return-an-error">
  ### エラーを返す
</div>

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

たとえば、`errorCode` パラメータに `user_exists` を指定してエラーを返すことができます。

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

その場合、Auth0 は `fs` テナントログイベントを記録します。

| テナントログイベントの項目 | 値                          |
| ------------- | -------------------------- |
| **コード**       | `fs`                       |
| **イベント**      | サインアップ失敗                   |
| **説明**        | `My custom error message.` |

<div id="user-object-parameter">
  ## User オブジェクトのパラメータ
</div>

`user` オブジェクト パラメータには、ユーザー作成プロセスに由来する、あらかじめ定義された一連のプロパティが含まれます。

| プロパティ           | 説明                                                                                                                                      |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `client_id`     | ユーザーが Universal Login 経由でサインアップした場合は Auth0 アプリケーションのクライアント ID、Auth0 Dashboard または Management API 経由で作成された場合は API キーです。                  |
| `tenant`        | Auth0 テナント名です。                                                                                                                          |
| `email`         | ユーザーのメールアドレスです。                                                                                                                         |
| `password`      | ユーザーのパスワード (平文) です。                                                                                                                     |
| `username`      | ユーザーのユーザー名です。[**Requires Username**](/docs/ja-jp/authenticate/database-connections/require-username) 設定がカスタムデータベース接続で有効になっている場合にのみ必須です。 |
| `connection`    | Auth0 接続名です。                                                                                                                            |
| `user_metadata` | ユーザーの Auth0 プロファイルに `user_metadata` オブジェクトが存在する場合は、その `user_metadata` オブジェクトのプロパティが含まれます。                                               |
| `app_metadata`  | ユーザーの Auth0 プロファイルに `app_metadata` オブジェクトが存在する場合は、その `app_metadata` オブジェクトのプロパティが含まれます。                                                 |

<div id="username-property">
  ### username プロパティ
</div>

カスタムデータベース接続で [Requires Username](/docs/ja-jp/authenticate/database-connections/require-username) 設定が有効になっている場合、[Login](/docs/ja-jp/authenticate/database-connections/custom-db/templates/login) スクリプトと [Get User](/docs/ja-jp/authenticate/database-connections/custom-db/templates/get-user) スクリプトは `username` プロパティに対応している必要があるため、これを外部データベースに保存しておく必要があります。

<div id="user-and-app-metadata">
  ### ユーザーとアプリのメタデータ
</div>

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

<div id="custom-sign-up-fields">
  ### カスタムのサインアップフィールド
</div>

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

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

<div id="language-specific-script-examples">
  ## 言語別のスクリプト例
</div>

Auth0 では、次の言語／テクノロジー向けのサンプルスクリプトを提供しています。

<CodeGroup>
  ```javascript JavaScript lines expandable theme={null}
  function create(user, callback) {
    // このスクリプトでは、既存のデータベースにユーザーエントリを作成します。スクリプトは、
    // ユーザーがサインアップを試みたとき、または Auth0 ダッシュボードや Management API を通じて
    // ユーザーが作成されたときに実行されます。
    // このスクリプトの実行が完了すると、ユーザーが正常に作成されたことを確認するために、
    // 直後に Login スクリプトが実行されます。
    //
    // ユーザーオブジェクトには常に次のプロパティが含まれます:
    // * email: ユーザーのメールアドレス
    // * password: ユーザーが入力した平文のパスワード
    // * tenant: この Auth0 アカウントの名前
    // * client_id: ユーザーがサインアップしたアプリケーションのクライアントID、または
    //              Management API または Auth0 ダッシュボードを通じて作成された場合の API キー
    // * connection: このデータベース接続の名前
    //
    // このスクリプトの終了方法は3通りあります:
    // 1. ユーザーが正常に作成された
    //     callback(null);
    // 2. このユーザーは既にデータベースに存在する
    //     callback(new ValidationError("user_exists", "my error message"));
    // 3. データベースに接続しようとした際に問題が発生した
    //     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));
  }
  ```

  ```javascript ASP.Net MVC3 lines expandable theme={null}
  // ASP.NET Membership Provider 用（MVC3 - Universal Providers）
  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);
    }
  }
  ```

  ```javascript ASP.Net MVC4 lines expandable theme={null}
  // For ASP.NET Membership Provider (MVC4 - Simple Membership)
  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
     *
     * この関数は、HMAC SHA256アルゴリズムを使ってパスワードをハッシュ化します。
     *
     * @password    {[string]}    ハッシュ化するパスワード
     * @salt        {[string]}    ハッシュ化処理で使用するsalt
     * @callback    {[function]}  パスワードのハッシュ化後に呼び出されるコールバック
     */
    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);
    });
  }
  ```

  ```javascript MongoDB 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);
          });
        });
      });
    });
  }
  ```

  ```javascript MySQL lines expandable 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);
      });
    });
  }
  ```

  ```javascript PostgreSQL lines expandable theme={null}
  function create(user, callback) {
    //この例では「pg」ライブラリを使用します
    //詳細: 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) {
          // 注: データベース接続を閉じるため、ここでは必ず`done()`を呼び出してください
          done();
          return callback(err);
        });
      });
    });
  }
  ```

  ```javascript SQL Server lines expandable theme={null}
  function create(user, callback) {
    //この例では「tedious」ライブラリを使用します
    //詳細: 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);
      });
    });
  }
  ```

  ```javascript Azure SQL Database lines expandable theme={null}
  function create (user, callback) {
    //この例では「tedious」ライブラリを使用しています
    //詳細はこちら: 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) {
      // デバッグメッセージを有効にするには、次の行のコメントを解除してください
      // 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); }
      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);
      });
    });
  }
  ```

  ```javascript Basic Auth request lines theme={null}
  function create(user, callback) {
    const request = require('request');
    request.post({
      url: 'https://myserviceurl.com/users',
      json: user
      //その他のオプションについては以下を参照:
      //https://github.com/mikeal/request#requestoptions-callback
    }, function(err, response, body) {
      if (err) return callback(err);
      callback(null);
    });
  }
  ```
</CodeGroup>

<div id="troubleshoot">
  ## トラブルシューティング
</div>

外部ユーザーストアまたは Auth0 のいずれかでユーザーを作成できない場合:

1. [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) エンドポイントまたは [接続ユーザーを削除](https://auth0.com/docs/api/management/v2#!/Connections/delete_users_by_email) エンドポイントを使用します。
3. **インポートモード**が無効になっていることを確認してから、Create スクリプトを設定します。
