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

# Change Password データベースアクションスクリプトとテンプレート

> Change Password スクリプトは、管理者またはユーザーがパスワード変更ワークフローを開始すると実行されます。

Change Password スクリプトは、外部データベース内の指定したユーザーのパスワードを変更するための定義済み関数を実装します。この関数名は `changePassword` にすることをお勧めします。

このスクリプトは、[レガシー認証シナリオ](/docs/ja-jp/authenticate/database-connections/custom-db/overview-custom-db-connections)でのみ使用され、外部データベース内のユーザーのパスワードを変更する場合に必要です。これは、ユーザーが[パスワードリセットのワークフロー](/docs/ja-jp/customize/login-pages/classic-login/customize-password-reset-page)を実行したとき、または <Tooltip tip="Auth0 Dashboard: サービスを設定するための Auth0 の主要製品。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=Auth0+Dashboard">Auth0 Dashboard</Tooltip> または Auth0 <Tooltip tip="Management API: お客様が管理タスクを実行できるようにする製品。" cta="用語集を見る" href="/docs/ja-jp/glossary?term=Management+API">Management API</Tooltip> からパスワード変更ワークフローが開始されたときに実行されます。

<div id="changepassword-function">
  ## ChangePassword function
</div>

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

* 外部データベース内のユーザーのパスワードを更新すること。
* パスワード変更に成功した場合は、`true` (または `last_password_reset` プロパティを含むオブジェクト) を返すこと。オブジェクトに `last_password_reset` プロパティが含まれている場合は、その値がユーザーのプロファイルに反映されます。
* パスワード変更に失敗した場合は、`false` を返すこと。
* 外部データベースに接続できない場合は、エラーを返すこと。

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

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

```js lines theme={null}
changePassword(email, newPassword, callback): function
```

| パラメータ         | 型        | 説明                                                                                           |
| ------------- | -------- | -------------------------------------------------------------------------------------------- |
| `email`       | String   | Auth0 および外部データベースにおけるユーザーのメールアドレス。                                                           |
| `newPassword` | String   | 外部データベースでユーザーの新しいパスワードとして設定する値。この値は平文で関数に送信されるため、外部データベースに送信する前に[暗号化する必要があります](#Encryption)。 |
| `callback`    | Function | パイプラインを通じてデータや処理結果を渡すために使用するコールバック関数。                                                        |

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

これは、`changePassword` 関数の実装方法を示す擬似的なJavaScriptの例です。各言語の例については、[言語別スクリプト例](#language-specific-script-examples)をご覧ください。

```javascript lines expandable theme={null}
function changePassword(email, newPassword, callback) {
  // 指定されたパスワードをハッシュ化する 
  let hashedPassword = hash(newPassword);

  // API呼び出しを準備する
  let options = {
    url: "https://example.com/api/users",
    body: {
      email: email,
      password: hashedPassword
    }
  };

  // APIを呼び出す
  send(options, err => {
    if (err && err.id == "FAIL_CHANGE_PASSWORD") {
      // パスワード変更に失敗した場合はコールバックでfalseを返す
      return callback(null, false);
    } else if (err) {
      // その他のエラーが発生した場合はコールバックでエラーを返す
      return callback(new Error("My custom error message.");
    } else {
      // パスワード変更が成功した場合はコールバックでtrueを返す
      return callback(null, true);

      // または、パスワード変更が成功した場合は、`last_password_reset`プロパティを
      // 含むオブジェクトを返すこともできる。
      // オブジェクトに`last_password_reset`プロパティが存在する場合、
      // ユーザーのプロファイルに反映される。
      return callback(null, { "last_password_reset": Date.now() });
    }
  });
}
```

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

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

たとえば：

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

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

`callback` 関数は 2 つのパラメータを受け取り、エラー情報を渡したり、処理の結果を示したりするために使用されます。

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

```js lines theme={null}
callback(error, operationResult | resultObj): function
```

| パラメータ             | 型       | 必須 | 説明                                                                             |
| ----------------- | ------- | -- | ------------------------------------------------------------------------------ |
| `error`           | オブジェクト  | 必須 | エラーデータが含まれます。                                                                  |
| `operationResult` | Boolean | 任意 | パスワード変更処理の結果を示します。                                                             |
| `resultObj`       | オブジェクト  | 任意 | パスワード変更処理が成功したことを示します。`last_password_reset` プロパティが存在する場合は、ユーザーのプロファイル上で更新されます。 |

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

パスワード変更処理が成功した場合は、`callback` 関数を呼び出し、`error` パラメータに `null` を、`operationResult` パラメータに `true` を渡します。例：

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

<div id="return-a-success-and-update-last_password_reset-attribute">
  ### 成功を返し、last\_password\_reset 属性を更新する
</div>

パスワード変更処理が成功した場合は、`callback` 関数を返し、`error` パラメータには `null` を、`profile` パラメータにはオブジェクトを渡します。オブジェクトに `last_password_reset` 属性が含まれている場合、その値はユーザーのプロファイルに更新されます。例:

```js lines theme={null}
return callback(null, { "last_password_reset": Date.now() });
```

<div id="return-a-failure">
  ### 失敗を返す
</div>

パスワード変更処理が失敗した場合は、`callback` 関数を呼び出し、`error` パラメータには `null` を、`operationResult` パラメータには `false` を渡します。例:

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

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

エラーが発生した場合は、`callback` 関数に関連するエラー情報を `error` パラメータとして渡します。例：

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

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

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

<CodeGroup>
  ```javascript JavaScript lines expandable theme={null}
  function changePassword(email, newPassword, callback) {
    // このスクリプトでは、現在のユーザーのデータベースに保存されているパスワードを変更します。
    // ユーザーがパスワードリセットのリクエスト後に確認リンクをクリックすると実行されます。
    // パスワード確認メールの内容と動作は、こちらでカスタマイズできます。
    // https://manage.auth0.com/#/emails
    // この関数の `newPassword` パラメータは平文です。データベースに保存されている値に
    // 合わせてハッシュ化し、saltを付加する必要があります。
    //
    // このスクリプトの完了方法は3通りあります。
    // 1. ユーザーのパスワードが正常に更新された場合:
    //     callback(null, true);
    // 2. ユーザーのパスワードが更新されなかった場合:
    //     callback(null, false);
    // 3. データベースへの接続中に問題が発生した場合:
    //     callback(new Error("my error message"));
    //
    // エラーが返された場合、確認リンクをクリックした後にユーザーがリダイレクトされるページの
    // クエリ文字列に渡されます。たとえば、`callback(new Error("error"))` を返して
    // https://example.com にリダイレクトすると、次のURLにリダイレクトされます。
    //     https://example.com?email=alice%40example.com&message=error&success=false
    const msg = 'Please implement the Change Password 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 changePassword(email, newPassword, callback) {
    var crypto = require('crypto');
    var Connection = require('tedious').Connection;
    var Request = require('tedious').Request;
    var TYPES = require('tedious').TYPES
    var connection = new Connection({
      userName:  'the username',
      password:  'the password',
      server:    'the server',
      options: {
        database:  'the db name',
        // encrypt: true   Windows Azure の場合はこれを有効にする
      }
    });
    /**
     * hashPassword
     *
     * この関数は、データベースに保存するパスワードのハッシュを作成します。
     *
     * @password  {[string]}      ユーザーが入力したパスワード
     * @return    {[string]}      ハッシュ化されたパスワード
     */
    function hashPassword(password, salt) {
      // デフォルトの実装は HMACSHA256 を使用し、キー長が64バイト、
      // デフォルトのソルトが16バイトのため、Membership はソルトを繰り返してバッファを埋めます
      var key = Buffer.concat([salt, salt, salt, salt]);
      var hmac = crypto.createHmac('sha256', key);
      hmac.update(Buffer.from(password, 'ucs2'));
      var hashed = hmac.digest('base64');
      return hashed;
    }
    connection.on('debug', function(text) {
        // 接続に問題がある場合は、詳細情報を得るためにこのコメントを外してください
        //console.log(text);
    }).on('errorMessage', function(text) {
        // SQL データベースへの接続時や SQL 文の実行時のエラーを表示します
      console.log(JSON.stringify(text));
    });
    connection.on('connect', function (err) {
      if (err) {
        return callback(err);
      }
      updateMembershipUser(email, newPassword, function(err, wasUpdated) {
        if (err) {
          return callback(err); // これは 500 を返します
        }
        callback(null, wasUpdated);
      });
    });
    function updateMembershipUser(email, newPassword, callback) {
      var salt            = crypto.randomBytes(16);
      var hashedPassword  = hashPassword(newPassword, salt);
      var updateMembership =
        'UPDATE Memberships '+
        'SET Password=@NewPassword, PasswordSalt=@NewSalt, LastPasswordChangedDate=GETDATE() '+
        'WHERE Email=@Email';
      var updateMembershipQuery = new Request(updateMembership, function (membershipErr, membershipCount) {
        if (membershipErr) {
          return callback(membershipErr);
        }
        callback(null, membershipCount > 0);
      });
      updateMembershipQuery.addParameter('NewPassword', TYPES.VarChar, hashedPassword);
      updateMembershipQuery.addParameter('NewSalt',     TYPES.VarChar, salt.toString('base64'));
      updateMembershipQuery.addParameter('Email',       TYPES.VarChar, email);
      connection.execSql(updateMembershipQuery);
    }
  }
  ```

  ```javascript ASP.NET MVC4 lines expandable theme={null}
  // ASP.NET Membership Provider（MVC4 - Simple Membership）の場合：
  function changePassword(email, newPassword, callback) {
    var crypto = require('crypto');
    var Connection = require('tedious').Connection;
    var Request = require('tedious').Request;
    var TYPES = require('tedious').TYPES
    var connection = new Connection({
      userName:  'the username',
      password:  'the password',
      server:    'the server',
      options: {
        database:  'the db name',
        // encrypt: true   Windows Azureの場合はこれを有効にする
      }
    });
    /**
     * hashPassword
     *
     * この関数は、HMAC SHA256アルゴリズムを使用してパスワードをハッシュ化します。
     *
     * @password    {[string]}    ハッシュ化するパスワード
     * @salt        {[string]}    ハッシュ化プロセスで使用するsalt
     * @callback    {[function]}  パスワードのハッシュ化後に呼び出すコールバック
     */
    function hashPassword(password, salt, callback) {
      var iterations         = 1000;
      var passwordHashLength = 32;
      crypto.pbkdf2(password, salt, iterations, passwordHashLength, function (err, hashed) {
        if (err) {
          return callback(err);
        }
        var result = Buffer.concat([Buffer.from([0], 1), salt, Buffer.from(hashed, 'binary')]);
        var resultBase64 = result.toString('base64');
        callback(null, resultBase64);
      });
    }
    connection.on('debug', function(text) {
        // 接続に問題がある場合は、詳細情報を確認するためにコメントアウトを解除する
        //console.log(text);
    }).on('errorMessage', function(text) {
        // SQLデータベースへの接続時またはSQLステートメント実行時のエラーを表示する
      console.log(JSON.stringify(text));
    });
    connection.on('connect', function (err) {
      if (err) {
        return callback(err);
      }
      updateMembershipUser(email, newPassword, function(err, wasUpdated) {
        if (err) {
          return callback(err); // 500を返す
        }
        callback(null, wasUpdated);
      });
    });
    function findUserId(email, callback) {
      var findUserIdFromEmail =
        'SELECT UserProfile.UserId FROM ' +
        'UserProfile INNER JOIN webpages_Membership ' +
        'ON UserProfile.UserId = webpages_Membership.UserId ' +
        'WHERE UserName = @Email';
      var findUserIdFromEmailQuery = new Request(findUserIdFromEmail, function (err, rowCount, rows) {
        if (err) {
          return callback(err);
        }
        // このメールアドレスに該当するレコードは見つかりませんでした
        if (rowCount < 1) {
          return callback(null, null);
        }
        var userId = rows[0][0].value;
        callback(null, userId);
      });
      findUserIdFromEmailQuery.addParameter('Email', TYPES.VarChar, email);
      connection.execSql(findUserIdFromEmailQuery);
    }
    function updateMembershipUser(email, newPassword, callback) {
      findUserId(email, function (err, userId) {
        if (err) {
          return callback(err);
        }
        if (userId === null) {
          return callback();
        }
        var salt = crypto.randomBytes(16);
        var updateMembership =
          'UPDATE webpages_Membership '+
          'SET Password=@NewPassword, PasswordChangedDate=GETDATE() '+
          'WHERE UserId=@UserId';
        var updateMembershipQuery = new Request(updateMembership, function (err, rowCount) {
          if (err) {
            return callback(err);
          }
          if (rowCount < 1) {
            return callback();
          }
          callback(null, rowCount > 0);
        });
        hashPassword(newPassword, salt, function (err, hashedPassword) {
          if (err) {
            return callback(err);
          }
          updateMembershipQuery.addParameter('NewPassword',   TYPES.VarChar, hashedPassword);
          updateMembershipQuery.addParameter('UserId',        TYPES.VarChar, userId);
          connection.execSql(updateMembershipQuery);
        });
      });
    }
  }
  ```

  ```javascript MongoDB lines theme={null}
  function changePassword(email, newPassword, 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');
      bcrypt.hash(newPassword, 10, function (err, hash) {
        if (err) {
          client.close();
          return callback(err);
        }
        users.update({ email: email }, { $set: { password: hash } }, function (err, count) {
          client.close();
          if (err) return callback(err);
          callback(null, count > 0);
        });
      });
    });
  }
  ```

  ```javascript MySQL lines theme={null}
  function changePassword(email, newPassword, callback) {
    const mysql = require('mysql');
    const bcrypt = require('bcrypt');
    const connection = mysql({
      host: 'localhost',
      user: 'me',
      password: 'secret',
      database: 'mydb'
    });
    connection.connect();
    const query = 'UPDATE users SET password = ? WHERE email = ?';
    bcrypt.hash(newPassword, 10, function(err, hash) {
      if (err) return callback(err);
      connection.query(query, [ hash, email ], function(err, results) {
        if (err) return callback(err);
        callback(null, results.length > 0);
      });
    });
  }
  ```

  ```javascript PostgreSQL lines theme={null}
  function changePassword (email, newPassword, 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(newPassword, 10, function (err, hash) {
        if (err) return callback(err);
        const query = 'UPDATE users SET password = $1 WHERE email = $2';
        client.query(query, [hash, email], function (err, result) {
          // 注: データベースへの接続を閉じるために、
          // ここでは常に `done()` を呼び出してください
          done();
          return callback(err, result && result.rowCount > 0);
        });
      });
    });
  }
  ```

  ```javascript SQL Server lines expandable theme={null}
  function changePassword (email, newPassword, callback) {
    //この例では「tedious」ライブラリを使用します
    //詳細はこちら: http://tediousjs.github.io/tedious/
    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 = 'UPDATE dbo.Users SET Password = @NewPassword 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, rows) {
        if (err) return callback(err);
        callback(null, rows > 0);
      });
      bcrypt.hash(newPassword, 10, function (err, hash) {
        if (err) return callback(err);
        request.addParameter('NewPassword', TYPES.VarChar, hash);
        request.addParameter('Email', TYPES.VarChar, email);
        connection.execSql(request);
      });
    });
  }
  ```

  ```javascript Azure SQL Database lines expandable theme={null}
  function changePassword (email, newPassword, 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 = 'UPDATE dbo.Users SET Password = @NewPassword ' +
      '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); }
      var request = new Request(query, function (err, rows) {
        if (err) { return callback(err); }
        console.log('rows: ' + rows);
        callback(null, rows > 0);
      });
      bcrypt.hash(newPassword, 10, function (err, hash) {
        if (err) { return callback(err); }
        request.addParameter('NewPassword', TYPES.VarChar, hash);
        request.addParameter('Email', TYPES.VarChar, email);
        connection.execSql(request);
      });
    });
  }
  ```
</CodeGroup>
