ユーザー移行 Lambda トリガーで別アカウントの Cognito ユーザープールへパスワードごとユーザーを移行してみた

ユーザー移行 Lambda トリガーで別アカウントの Cognito ユーザープールへパスワードごとユーザーを移行してみた

Amazon Cognito のユーザープールを別アカウントに移行する際、パスワードを引き継げるユーザー移行 Lambda トリガーの実装方法を、MFA 必須のプール対応で詳しく紹介します。
2026.11.01

製造ビジネステクノロジー部の小林です。

最近、Amazon Cognito のユーザープールを別アカウントに移す場面がありました。CSV のインポート機能ではパスワードが引き継がれず、全ユーザーにパスワードの再設定をお願いすることになります。

そこで、パスワードをそのまま引き継げるユーザー移行 Lambda トリガーを使い、アカウント A のユーザープールからアカウント B へユーザーを移行してみました。

移行元のユーザープールは、MFA(E メールのワンタイムコード)を必須にしています。
MFA 必須のプールでもパスワードを引き継げるのか、あわせて確認します。

全体の流れ

ユーザーから見ると、移行先のアプリケーションに今までと同じユーザー名とパスワードでサインインするだけです。裏側では次のことが起きています。

  1. 移行先にユーザーが存在しないため、Cognito が移行 Lambda を呼び出す
  2. Lambda が移行元アカウントのロールを引き受け、移行元で同じ認証情報を検証する。移行元は MFA 必須なので、パスワードが正しければトークンではなく EMAIL_OTP チャレンジが返る
  3. チャレンジが返った時点でパスワードは正しいと分かるので、移行元のユーザー属性を取得して返す
  4. 移行先も MFA 必須なので、移行先からワンタイムコードが送られる。ユーザーがコードを入力すると、移行先にユーザーが作成され、入力されたパスワードがそのまま保存される

https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/user-pool-lambda-migrate-user.html |

検証環境

項目 内容
リージョン 東京(ap-northeast-1)。両アカウントとも同じ
アカウント A(移行元) ユーザープール、移行用アプリクライアント、クロスアカウント用 IAM ロール
アカウント B(移行先) ユーザープール、アプリクライアント、移行 Lambda
サインイン識別子と必須属性 ユーザー名、email(両プールで揃える)
MFA 必須。E メールのワンタイムコード(両プールで同じ)
メール送信 Amazon SES。サンドボックスのまま、検証済みのメールアドレスだけに送る
Lambda ランタイム Python 3.13

クロスアカウント構成では「B の Lambda 実行ロールの ARN を A のロールの信頼ポリシーに書く」「A のロールの ARN を B の Lambda の環境変数に書く」という相互参照があるため、次の順番で進めます。

  1. アカウント A: SES の検証済み ID、移行元ユーザープール、テストユーザー、移行用アプリクライアント
  2. アカウント B: SES の検証済み ID、移行先ユーザープールとアプリクライアント
  3. アカウント B: Lambda 関数(実行ロールの ARN を控える)
  4. アカウント A: Lambda 実行ロールを信頼するクロスアカウント用ロール(ロールの ARN を控える)
  5. アカウント B: Lambda 実行ロールに sts:AssumeRole を許可し、環境変数とトリガーを設定
  6. 動作確認

1. 移行元(アカウント A)を用意する

SES の検証済み ID

E メール MFA を使うには、ユーザープールのメール送信を自分の SES リソースにしておく必要があります。

SES コンソールの [ID] から [ID の作成] を選び、ID タイプに E メールアドレスを選んで送信元のアドレスを登録し、届いた確認メールのリンクを開いて検証済みにします。

SES はサンドボックスのままなので、検証済みのアドレス宛てにしか送れません。今回はこのアドレスをテストユーザーのメールアドレスにも使います。

https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/user-pool-settings-mfa-sms-email-message.html

ユーザープール

移行元のプールは検証用に作ります。ウィザードでアプリケーションタイプに SPA を選び、サインイン識別子をユーザー名、必須属性を email にします。

作成後、プール名を migration-source-pool に変え、メール送信と MFA を設定します。

設定 場所 値
E メール [認証] の [認証方法] Amazon SES で送信。送信元に検証済み ID、送信者の名前は Source <検証済みのアドレス>
MFA [認証] の [サインイン] MFA を必須にする。方法は E メールメッセージ
MFA メッセージの件名 [ブランディング] の [メッセージテンプレート] [移行元] 認証コード

テストユーザー

[ユーザー] からテストユーザーを 3 名作成します。メールアドレスは SES で検証済みのものを使い、確認済みにしておきます。

コンソールから作成したユーザーは FORCE_CHANGE_PASSWORD 状態なので、CLI でパスワードを恒久的に設定して CONFIRMED にします。

# 移行元ユーザープールの ID([概要] の「ユーザープール ID」)
SRC_POOL_ID=ap-northeast-1_xxxxxxxxx

for u in test-user-1 test-user-2 test-user-3; do
  aws cognito-idp admin-set-user-password \
    --user-pool-id "$SRC_POOL_ID" \
    --username "$u" \
    --password 'Passw0rd!' \
    --permanent \
    --profile src
done

aws cognito-idp list-users \
  --user-pool-id "$SRC_POOL_ID" \
  --query 'Users[].[Username,UserStatus]' \
  --output table \
  --profile src
------------------------------
|          ListUsers         |
+--------------+-------------+
|  test-user-3 |  CONFIRMED  |
|  test-user-1 |  CONFIRMED  |
|  test-user-2 |  CONFIRMED  |
+--------------+-------------+

移行用のアプリクライアント

Lambda が移行元で認証するための、移行専用のアプリクライアントを作ります。[アプリケーション] の [アプリケーションクライアント] から、アプリケーションタイプを SPA、名前を migration-source-client にして作成します。

SPA を選ぶのはクライアントシークレットなしで作るためです。シークレットは作成後に外せず、付いていると Lambda 側で SECRET_HASH の計算が必要になります。

作成直後の認証フローには管理者 API によるパスワード認証が含まれていません。

「アプリケーションクライアントに関する情報」の [編集] を開き、「サーバー側の管理者認証情報 (ALLOW_ADMIN_USER_PASSWORD_AUTH) を使用してサインインします」にチェックを入れて保存し、クライアント ID を控えます。

ウィザードが作ったクライアント(今回は source-app)とは別物なので、取り違えないようにします。

MFA 必須のプールで AdminInitiateAuth が何を返すか確認する

Lambda を書く前に、移行元で AdminInitiateAuth を直接呼び出しておきます。

# 移行用アプリクライアント migration-source-client のクライアント ID
SRC_CLIENT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxx

aws cognito-idp admin-initiate-auth \
  --user-pool-id "$SRC_POOL_ID" \
  --client-id "$SRC_CLIENT_ID" \
  --auth-flow ADMIN_USER_PASSWORD_AUTH \
  --auth-parameters USERNAME=test-user-1,PASSWORD='Passw0rd!' \
  --query '{Challenge:ChallengeName,Params:ChallengeParameters}' \
  --profile src
{
  "Challenge": "EMAIL_OTP",
  "Params": {
    "CODE_DELIVERY_DELIVERY_MEDIUM": "EMAIL",
    "CODE_DELIVERY_DESTINATION": "k***@c***",
    "USER_ID_FOR_SRP": "test-user-1"
  }
}

MFA 必須のプールでは、パスワードが正しくてもトークンは返らず、EMAIL_OTP チャレンジが返ります(このときコードのメールも送られます)。パスワードが違うときは次のエラーになります。

An error occurred (NotAuthorizedException) when calling the AdminInitiateAuth operation: Incorrect username or password.

つまり MFA のチャレンジが返った時点でパスワードの検証は済んでいます。移行 Lambda は「トークンが返った」または「MFA のチャレンジが返った」をパスワード一致とみなします。

2. 移行先(アカウント B)のユーザープールを作成する

アカウント B でも SES の検証済み ID を作ります(SES の ID はアカウントをまたいで使えません)。ユーザープールは、サインイン識別子と必須属性を移行元と同じにして作成します。

作成後、プール名を migration-dest-pool にし、移行元と同じように E メール設定を SES に切り替え、MFA を必須の E メールメッセージにします。

アプリクライアントはウィザードが作った migration-dest-client を使います。「アプリケーションクライアントに関する情報」の [編集] で「ユーザー名とパスワード (ALLOW_USER_PASSWORD_AUTH) を使用してサインインします」にチェックを追加します。

SRP ではパスワードがサーバーに届かずトリガーが呼び出されないため、移行期間中はこのフローが必要です。

3. 移行 Lambda を作成する(アカウント B)

関数の作成

Lambda のコンソールで、関数名 cognito-user-migration、ランタイム Python 3.13、実行ロールは新規作成で関数を作ります。

作成後、[設定] の [一般設定] でタイムアウトを 5 秒にします。Cognito が待つのは 5 秒までです。同じ画面の実行ロールの ARN を控えておきます。

関数コード

コードは、開発者ガイドの例と、AWS re:Post の記事「How to setup cross-account Cognito User Pool migration with the Migrate User Lambda Trigger」の Python テンプレートを元に、MFA 必須のプール向けに手を加えたものです。

https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/user-pool-lambda-migrate-user.html#aws-lambda-triggers-user-migration-example-1

https://repost.aws/articles/ARUU-fzUyeSMWVUj46mVX6CQ/how-to-setup-cross-account-cognito-user-pool-migration-with-the-migrate-user-lambda-trigger

lambda_function.py
lambda_function.py
import logging
import os

import boto3
from botocore.config import Config
from botocore.exceptions import ClientError

logger = logging.getLogger()
logger.setLevel(logging.INFO)

# 移行元(アカウント A)の情報。環境変数で渡す
SRC_ROLE_ARN = os.environ["SRC_ROLE_ARN"]
SRC_POOL_ID = os.environ["SRC_POOL_ID"]
SRC_CLIENT_ID = os.environ["SRC_CLIENT_ID"]
SRC_REGION = os.environ.get("SRC_REGION", "ap-northeast-1")

# Cognito は Lambda の応答を 5 秒までしか待たない。
# 既定値(接続・読み取りとも 60 秒、リトライあり)のままだと、
# 移行元の API が遅延したときに 5 秒を超えて待ち続けるため、1 回の通信を短く切る
API_CONFIG = Config(
    connect_timeout=1,
    read_timeout=3,
    retries={"total_max_attempts": 1},
)

# 上の設定は 1 回の通信ごとの上限なので、API を順に呼ぶと合計で 5 秒を超え得る。
# 各 API を呼ぶ前に残り時間を確認し、足りなければ呼ばずに終了する(ミリ秒)
TIME_BUDGET_MS = {
    "admin_initiate_auth": 2000,
    "admin_get_user": 700,
}

# 「認証情報が正しくない」として扱う AdminInitiateAuth のエラー。
# これ以外(スロットリング、メール送信の失敗、設定の誤りなど)は障害として扱う
AUTH_FAILURE_CODES = {
    "NotAuthorizedException",
    "UserNotFoundException",
    "UserNotConfirmedException",
    "PasswordResetRequiredException",
}

# 移行先にコピーしない属性。sub は移行先で新しく採番される
EXCLUDED_ATTRIBUTES = {"sub", "identities"}

# パスワード検証のあとに返る MFA 系のチャレンジ。これが返ればパスワードは正しい
MFA_CHALLENGES = {
    "EMAIL_OTP",
    "SMS_MFA",
    "SOFTWARE_TOKEN_MFA",
    "SELECT_MFA_TYPE",
    "MFA_SETUP",
}

sts = boto3.client("sts", config=API_CONFIG)

class MigrationError(Exception):
    """利用者に見せてよい文言だけを持つ例外。メッセージはクライアントに返る"""

def source_cognito_client():
    """移行元アカウントのロールを引き受け、その認証情報で Cognito クライアントを作る"""
    credentials = sts.assume_role(
        RoleArn=SRC_ROLE_ARN,
        RoleSessionName="cognito-user-migration",
    )["Credentials"]
    return boto3.client(
        "cognito-idp",
        region_name=SRC_REGION,
        config=API_CONFIG,
        aws_access_key_id=credentials["AccessKeyId"],
        aws_secret_access_key=credentials["SecretAccessKey"],
        aws_session_token=credentials["SessionToken"],
    )

def to_user_attributes(attributes):
    """AdminGetUser の属性リストを、レスポンス用の辞書に変換する"""
    return {
        a["Name"]: a["Value"]
        for a in attributes
        if a["Name"] not in EXCLUDED_ATTRIBUTES
    }

def ensure_time_left(context, api):
    """次の API を呼ぶ時間が残っていなければ、Lambda のタイムアウトを待たずに終了する"""
    remaining = context.get_remaining_time_in_millis()
    if remaining < TIME_BUDGET_MS[api]:
        logger.warning("not enough time left for %s: %d ms", api, remaining)
        raise MigrationError("Migration failed")

def migrate(event, context, trigger_source, username):
    if trigger_source == "UserMigration_Authentication":
        idp = source_cognito_client()

        # 移行元で同じユーザー名・パスワードで認証できるか確認する
        ensure_time_left(context, "admin_initiate_auth")
        try:
            result = idp.admin_initiate_auth(
                UserPoolId=SRC_POOL_ID,
                ClientId=SRC_CLIENT_ID,
                AuthFlow="ADMIN_USER_PASSWORD_AUTH",
                AuthParameters={
                    "USERNAME": username,
                    "PASSWORD": event["request"]["password"],
                },
            )
        except ClientError as e:
            code = e.response["Error"]["Code"]
            if code not in AUTH_FAILURE_CODES:
                raise  # 障害として外側で記録する
            logger.info("source auth failed: %s", code)
            raise MigrationError("Bad credentials")

        challenge = result.get("ChallengeName")
        if "AuthenticationResult" not in result and challenge not in MFA_CHALLENGES:
            # NEW_PASSWORD_REQUIRED(仮パスワードのまま)などは移行しない
            logger.info("source auth returned challenge: %s", challenge)
            raise MigrationError("Bad credentials")
        logger.info("source auth ok challenge=%s", challenge)

        ensure_time_left(context, "admin_get_user")
        user = idp.admin_get_user(UserPoolId=SRC_POOL_ID, Username=username)
        event["response"]["userAttributes"] = to_user_attributes(user["UserAttributes"])
        event["response"]["finalUserStatus"] = "CONFIRMED"
        event["response"]["messageAction"] = "SUPPRESS"
        return event

    if trigger_source == "UserMigration_ForgotPassword":
        # パスワードが渡されない経路。E メール MFA のプールではリセットコードを
        # E メールに送れないため、パスワードを持たないユーザーを作らないように拒否する
        logger.info("forgot-password migration is not supported in this pool")
        raise MigrationError("Password reset is not available. Please contact support.")

    raise MigrationError(f"Bad triggerSource {trigger_source}")

def lambda_handler(event, context):
    trigger_source = event["triggerSource"]
    username = event["userName"]
    # event 全体を出力しない。request.password にパスワードが入っている
    logger.info("triggerSource=%s userName=%s", trigger_source, username)

    try:
        return migrate(event, context, trigger_source, username)
    except MigrationError:
        raise
    except Exception:
        # AssumeRole の失敗やスロットリングなど。詳細はログにだけ残し、
        # ロール ARN などを含む生のメッセージをクライアントに返さない
        logger.exception("migration failed unexpectedly")
        raise MigrationError("Migration failed")

ポイントは次のとおりです。

  • 移行元で AdminInitiateAuth(ADMIN_USER_PASSWORD_AUTH)を呼び、トークンか MFA 系チャレンジが返った場合だけ移行します。公式の例は AuthenticationResult 前提のため、MFA 必須の移行元ではそのままでは動きません
  • この判定で確認できるのはパスワードの一致までです。移行先でも同じメールアドレス宛ての MFA を行う今回の構成なら問題ありませんが、移行元が TOTP で認証アプリを登録し直す構成では MFA のリセットに相当するため、別の確認が必要です
  • NEW_PASSWORD_REQUIRED など MFA 以外のチャレンジでは移行しません

コードを貼り付けたら [Deploy] します。環境変数とトリガーはアカウント A のロールを作ってから設定します。

4. クロスアカウント用 IAM ロールを作成する(アカウント A)

アカウント A の IAM で、B の Lambda 実行ロールだけが引き受けられるロールを作ります。[ロールを作成] で信頼されたエンティティタイプに [カスタム信頼ポリシー] を選びます。

次の JSON を貼り付けます。Principal は手順 3 で控えた Lambda 実行ロールの ARN です。

trust-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::222222222222:role/service-role/cognito-user-migration-role-xxxxxxxx"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

ステップ 2 の「許可を追加」で [インラインポリシーを作成] を選び、移行元ユーザープールに対する AdminInitiateAuth と AdminGetUser だけを許可します。Resource は移行元ユーザープールの [概要] にある ARN です。

permission-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "cognito-idp:AdminInitiateAuth",
        "cognito-idp:AdminGetUser"
      ],
      "Resource": "arn:aws:cognito-idp:ap-northeast-1:111111111111:userpool/ap-northeast-1_xxxxxxxxx"
    }
  ]
}

ステップ 3 でロール名を cognito-migration-source-role にして作成し、ロールの ARN を控えます。

5. Lambda にロール引き受けの許可、環境変数、トリガーを設定する(アカウント B)

Lambda の [設定] の [アクセス権限] から実行ロールを開き、インラインポリシーで手順 4 のロールへの sts:AssumeRole を許可します。

assume-source-role.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "arn:aws:iam::111111111111:role/cognito-migration-source-role"
    }
  ]
}

[設定] の [環境変数] に次の 4 つを設定します。

キー 値
SRC_ROLE_ARN 手順 4 で作成したロールの ARN
SRC_POOL_ID 移行元ユーザープールの ID
SRC_CLIENT_ID 移行用アプリクライアントの ID
SRC_REGION ap-northeast-1

移行先ユーザープールの [認証] の [拡張機能] から [Lambda トリガーを追加] を選びます。トリガータイプは [サインアップ]、その下の [ユーザーを移行 トリガー] を選び、cognito-user-migration を割り当てます。

コンソールから割り当てると、Cognito が関数を呼び出すためのリソースベースポリシーが自動で追加されます。

6. 動作確認

実際のユーザーと同じように、マネージドログインの画面からサインインします。画面から見えない部分だけ CLI で確認します。

マネージドログインの準備

migration-dest-client の [ログインページ] タブを開きます。

移行元のパスワードでサインインする

移行先にユーザーがいない状態で [ログインページを表示] を選び、移行元と同じ test-user-1 とパスワードでサインインします。

移行先に存在しないユーザーなのに「ユーザー名またはパスワードが違う」とはならず、ワンタイムコードの入力画面に進みます。この裏で Lambda が動き、移行元の認証が通っています。

メールボックスには移行元と移行先から 2 通届きます。移行元のものは Lambda の AdminInitiateAuth で送られたもので、入力するのは移行先のコードです。

コードを入力するとサンプルページにリダイレクトされ、サインインが完了します。

移行先に作成されたユーザーを確認する

移行先の [ユーザー] に test-user-1 が「確認済み」で表示されます。

E メール MFA はデバイス登録を持たず email 属性で成り立つため、移行先でも初回からコードが届きました。
Lambda のログにはトリガーの種類、ユーザー名、チャレンジ名だけが出ていて、パスワードは出ていません。

[INFO] triggerSource=UserMigration_Authentication userName=test-user-1
[INFO] source auth ok challenge=EMAIL_OTP
REPORT RequestId: 109907ca-... Duration: 3181.85 ms Billed Duration: 3513 ms Memory Size: 128 MB Max Memory Used: 91 MB Init Duration: 330.51 ms

2 回目のサインインでは Lambda が呼ばれない

同じユーザーでもう一度サインインすると、移行先に保存されたパスワードで認証されます。届くメールは移行先からの 1 通だけで、Lambda のログに新しい行は増えません。

間違ったパスワードではユーザーが作られない

未移行の test-user-2 に間違ったパスワードでサインインすると、エラーになります。

Lambda のログでは移行元の認証に失敗し、Bad credentials の例外を投げています。

[INFO] triggerSource=UserMigration_Authentication userName=test-user-2
[INFO] source auth failed: NotAuthorizedException
[ERROR] MigrationError: Bad credentials

パスワードを忘れたユーザーの移行は、E メール MFA のプールでは成立しない

このトリガーには「パスワードをお忘れですか」から移行する経路もありますが、記事のコードではこの分岐で例外を投げています。

この状態で test-user-3 のリセットを試すと、エラーではなく「SMS でリセットコードを送りました」と表示されました。移行先には SMS の設定がなくユーザーも存在しないため、実際には何も送られていません。

これは「ユーザー存在エラーの防止」の動作です。存在しないユーザーへの ForgotPassword には、ユーザーの有無を悟られないよう、コードを送ったかのような応答を返します。

Lambda が例外を投げた場合も同様で、コードを入力しても先へは進みません。

https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/cognito-user-pool-managing-errors.html

利用者から見ると「コードが届かない」状態になるため、移行期間中はパスワードを忘れた場合の問い合わせ先を案内しておきます。対応は移行元のアプリの状態で決まります。

移行元のアプリが稼働中の場合

移行元で仮パスワードを発行し、本人に移行元で変更してもらってから移行します。

  1. 管理者が移行元のユーザープールで AdminSetUserPassword を実行し、仮パスワードを設定します。--permanent を付けないと、次回サインイン時に変更が必須の仮パスワードになります
  2. 本人が移行元のアプリに仮パスワードでサインインし、新しいパスワードを設定します
  3. 本人が新しいパスワードで移行先にサインインすると、通常どおり移行されます

移行元でも E メール MFA のためにパスワードの再設定を本人だけでは完了できないので、管理者による仮パスワードの発行が起点になります。

移行元のアプリを停止済みの場合

移行先に直接ユーザーを作ります。

  1. 管理者が移行先のユーザープールで AdminCreateUser を実行し、仮パスワード付きでユーザーを作成します。属性は移行元から転記します
  2. 本人が仮パスワードで移行先にサインインし、新しいパスワードの設定と E メール MFA を経て完了します

なお、ユーザーに phone_number を持たせて SMS でコードを受け取る構成なら、この経路はそのまま使えます。

最終的に、3 名とも移行先に揃いました。

移行時に押さえておきたいポイント

サインインしないユーザーは移行されないため、終わらせ方を決めておく

この方式はサインイン時に 1 人ずつ移す「遅延移行」なので、一度もサインインしないユーザーは移行されません。先に CSV インポートでユーザーを作ると、トリガーが呼ばれずパスワードを引き継げなくなります。

一方で移行 Lambda を残し続けると、アプリクライアントを USER_PASSWORD_AUTH のままにする必要があり、移行元のプールやクロスアカウントのロールも残ります。

移行先にいないユーザー名での試行はすべて移行元に転送されるため、総当たりの入口にもなります。次のように終わらせ方まで計画しておきます。

  1. サービスの利用間隔に合わせて移行期間を決める
  2. 移行元の list-users と移行先を突き合わせて未移行の人数を追う
  3. 残ったユーザーに、期限後はパスワードの再設定が必要になると案内する
  4. 期限後、未移行ユーザーを CSV インポートで作る(RESET_REQUIRED になる)。E メール MFA 必須のプールではセルフサービスのリセットができないため、管理者が AdminSetUserPassword で仮パスワードを発行する
  5. トリガーを外し、移行用クライアントとロールを削除する

移行元が MFA 必須でも移行できるが、初回はコードが 2 通届く

移行元が E メールや SMS の MFA だと、AdminInitiateAuth のたびに移行元からもコードが送られます。使うのは移行先のコードだけなので、件名や送信者名を変え、「初回のみ 2 通届く」と事前に案内しておくと混乱を防げます。

パスワードポリシーは検証されない

移行時は移行先のパスワードポリシーが適用されません。厳密に適用したい場合は、Lambda で強度を判定し、満たさないユーザーを finalUserStatus: RESET_REQUIRED にする方法が公式で案内されています。

https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/user-pool-lambda-migrate-user.html#cognito-user-pools-lambda-trigger-syntax-user-migration

移行されない情報

情報 扱い
sub 移行先で新しく採番される。sub をキーにしている場合は付け替えが必要
グループ 対象外。create-group、admin-add-user-to-group で再作成する
MFA デバイス(TOTP) 対象外。移行先で再登録(MFA_SETUP)が必要で、MFA のリセットに相当する。E メール・SMS MFA は属性が移ればそのまま使える
外部 IdP 経由のユーザー 対象外。フェデレーションではトリガーが呼ばれない
作成日時 移行した日時になる

まとめ

ユーザー移行 Lambda トリガーで、別アカウントの Cognito へユーザーをパスワードごと移してみました。Lambda は移行先に置き、移行元のロールを借りて API を 2 つ呼ぶだけなので、コードは 150 行ほどです。

移行元が E メール MFA 必須でも、「MFA のコードを求められた=パスワードは合っている」と判断すれば移行できます。

ただし、パスワードを忘れた人は移行できないので、その場合の対応は別に決めておきましょう。また、サインインしない人は移行されないため、移行期間をいつ終えるかも先に考えておくと安心です。

この記事をシェアする

関連記事