Auth0から外部DB(Amazon RDS)に接続してユーザー認証する そしてユーザーを外部DBからAuth0のユーザーストアへ自動移行してみる #Auth0

2023.10.12

こんにちは。ゲーソル新屋です。

今回はAuth0のCustom Database Connectionを使って

(1)Auth0から外部DB(Amazon RDS)に接続してユーザー認証
(2)ユーザーを外部DBからAuth0のユーザーストアへ自動移行

をやってみます。

ちなみにユーザー移行手段は全部で3つあります。
・Management API を使用したユーザーの一括インポート
・ユーザーインポート/エクスポートのExtensionを使用してユーザーを移行する
自動移行(トリクルマイグレーション)←今回検証する機能

では、やっていきます。

(1)Auth0から外部DB(Amazon RDS)に接続してユーザー認証

■Custom Database Connection を新規作成

■Auth0側のIPを控える

■既存DBセットアップ

今回のシナリオの既存DBとしてAmazon RDS(Aurora/MySQL)を新規作成
こちらを参考記事にしました

■Auth0側からのインバウンドアクセスを許可

■既存ユーザーデータ投入

user1〜3のユーザーでパスワード全員同じ 移行済かどうかのフラグをFALSEにしておく

mysql> select * from users;
+----+-------------------+--------------------------------------------------------------+----------+-------------+
| id | email             | password                                                     | nickname | is_migrated |
+----+-------------------+--------------------------------------------------------------+----------+-------------+
|  1 | user1@example.com | $2b$10$tiYl9C2I0t1hwuZ9m6IUiea4lgJlDIy/7HFAjTaWkLqfHfARvSfE6 | user1    |           0 |
|  2 | user2@example.com | $2b$10$tiYl9C2I0t1hwuZ9m6IUiea4lgJlDIy/7HFAjTaWkLqfHfARvSfE6 | user2    |           0 |
|  3 | user3@example.com | $2b$10$tiYl9C2I0t1hwuZ9m6IUiea4lgJlDIy/7HFAjTaWkLqfHfARvSfE6 | user3    |           0 |
+----+-------------------+--------------------------------------------------------------+----------+-------------+

テーブル定義はこんな感じ

 CREATE TABLE users (
     id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
     email VARCHAR(50) NOT NULL,
     password VARCHAR(100) NOT NULL,
     nickname VARCHAR(50),
     is_migrated BOOLEAN DEFAULT FALSE,
     UNIQUE (email)
 );

■Custom Database Connection に既存DBの接続情報を設定

■Database Action Script を実装

まずはLoginだけ テンプレートスクリプトがあるので簡単

コード全体はこんな感じ

function login(email, password, callback) {
  const mysql = require('mysql');
  const bcrypt = require('bcrypt');

  const connection = mysql.createConnection({
    host: configuration.TEST_DB_HOST,
    user: configuration.TEST_DB_USER,
    password: configuration.TEST_DB_PASSWORD,
    database: configuration.TEST_DB_DBNAME
  });

  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
      });
    });
  });
}

■アプリケーションでDatabaseを有効化

■動作確認

ここまでで、Auth0から外部のユーザーストアに接続できることを確認できました。

(2)ユーザーを外部DBからAuth0のユーザーストアへ自動移行

■自動移行を有効化

Database Action Script を修正

Loginの追加コードはこんな感じ

    bcrypt.compare(password, user.password, function(err, isValid) {
      if (err || !isValid) return callback(err || new WrongUsernameOrPasswordError(email));

      // ここから
      const query = 'UPDATE users SET is_migrated = true WHERE email = ?';
      connection.query(query, [ email ], function(err, results) {
        if (err) return callback(err);
      });
      // ここまで

      callback(null, {

Get userのコード全体はこんな感じ

function getByEmail(email, callback) {
  const mysql = require('mysql');

  const connection = mysql.createConnection({
    host: configuration.TEST_DB_HOST,
    user: configuration.TEST_DB_USER,
    password: configuration.TEST_DB_PASSWORD,
    database: configuration.TEST_DB_DBNAME
  });

  connection.connect();

  const query = 'SELECT id, nickname, email FROM users WHERE email = ?';

  connection.query(query, [ email ], function(err, results) {
    if (err || results.length === 0) return callback(err || null);

    const user = results[0];
    callback(null, {
      user_id: user.id.toString(),
      nickname: user.nickname,
      email: user.email
    });
  });
}

■動作確認

ログインを施行したユーザーはマイグレーション済みとなる

mysql> select * from users;
+----+-------------------+--------------------------------------------------------------+----------+-------------+
| id | email             | password                                                     | nickname | is_migrated |
+----+-------------------+--------------------------------------------------------------+----------+-------------+
|  1 | user1@example.com | $2b$10$tiYl9C2I0t1hwuZ9m6IUiea4lgJlDIy/7HFAjTaWkLqfHfARvSfE6 | user1    |           1 |
|  2 | user2@example.com | $2b$10$tiYl9C2I0t1hwuZ9m6IUiea4lgJlDIy/7HFAjTaWkLqfHfARvSfE6 | user2    |           1 |
|  3 | user3@example.com | $2b$10$tiYl9C2I0t1hwuZ9m6IUiea4lgJlDIy/7HFAjTaWkLqfHfARvSfE6 | user3    |           0 |
+----+-------------------+--------------------------------------------------------------+----------+-------------+

以上です。

まとめ

簡単に外部のユーザーストアと接続できました。Action ScriptはMySQL以外にもテンプレートがあり、ほとんどコードを書かないで設定完了しました。 外部のユーザーストアは何もRDSに限らず、Cognitoユーザープールなんかでも、カスタムデータベース接続できちゃいます。その場合、Action ScriptはAWS SDK for JavaScriptで実装することになりますね。

Action Scriptが対応しているライブラリは以下で確認できます。
https://auth0-extensions.github.io/canirequire/

AWS SDK for JavaScript v3が対応しているようですね。

また、自動移行に関しても徐々に移行できるので大量のユーザーを移行する場合に便利だと感じました。 大量データを一気にインポート・エクスポートしようとすると時間が掛かるため、移行作業によるメンテナンスを意識する必要があるのと
インポート・エクスポートする際のAuth0ManagementAPIのリクエスト制限に引っかかることがあるので、注意が必要です。