Amazon Cognito ユーザープールの作成後に属性を変更する方法を教えてください。

最終更新日: 2019 年 6 月 24 日

Amazon Cognito ユーザープールを作成しました。ユーザー登録に必要な標準属性を変更したいです。属性を変更するにはどうすれば良いですか?

簡単な説明

ユーザープールの作成後にユーザープールの標準属性を変更することはできません。その代わりに、ユーザー登録に必要な属性を持つ新しいユーザープールを作成してください。次に、AWS Lambda 関数をユーザー移行トリガーとして使用して、既存のユーザーを新しいユーザープールに移行します

注意: 既存のユーザープールにカスタム属性を追加できます。ただし、これらの属性はユーザー登録には必要ありません。

解決方法

異なる属性で新しいユーザープールを設定

新しいユーザープールを作成します。次に、設定中に (最後にプールの作成を選択する前)、好みに合わせて標準属性を編集します。

重要: ユーザープールで新しい必須属性を指定する場合、新しいユーザープールにこれらの新しい属性を提供するように Lambda 関数を設計する必要があります。そうでない場合、ユーザーの移行中に認証が失敗します。たとえば、古いユーザープールは E メールのみを必要としていましたが、新しいユーザープールでは E メール電話番号の両方が必要だとします。この場合、ユーザーを認証するには、電話番号の属性値を新しいユーザープールに渡す必要があります。

Lambda 関数の作成

Lambda コンソールエディタを使用するか、独自のデプロイパッケージを構築してアップロードすることにより、ユーザー移行 Lambda 関数を作成します。

こちらに、テストに使用できる Python 関数の例があります。

注意: UserPoolId は、値の例を古いユーザープールの ID に置き換えます。Amazon Cognito コンソールで、ユーザープールの管理ページの全般設定タブで ID を見つけます。ClientId は、値の例を古いユーザープールのアプリクライアント ID に置き換えます。Amazon Cognito コンソールでもアプリクライアント ID をお探しください。全般設定アプリクライアントを選択します。

重要: このサンプルコードは、古いユーザープールで Multi-Factor Authentication (MFA) を使用しているユーザーの移行に対しては機能しません。

# Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

import json
import boto3

client = boto3.client('cognito-idp')

def lambda_handler(event, context):
    if (event['triggerSource'] == 'UserMigration_Authentication'):
        user = client.admin_initiate_auth(
            UserPoolId='<user pool id of the user pool where the user already exists>',
            ClientId='<app client id of the user pool where the user already exists>',
            AuthFlow='ADMIN_NO_SRP_AUTH',
            AuthParameters={
                'USERNAME': event['userName'],
                'PASSWORD': event['request']['password']
            }
        )
        
        if (user):
            userAttributes = client.get_user(
                AccessToken=user['AuthenticationResult']['AccessToken']
            )
            for userAttribute in userAttributes['UserAttributes']:
                if userAttribute['Name'] == 'email':
                    userEmail = userAttribute['Value']
                    #print(userEmail)
                    event['response']['userAttributes'] = {
                        "email": userEmail,
                        "email_verified": "true"
                    }
            
            event['response']['messageAction'] = "SUPPRESS"
            print (event)
            return (event)
        else:
            return('Bad Password')
    elif (event["triggerSource"] == "UserMigration_ForgotPassword"):
        user = client.admin_get_user(
            UserPoolId='<user pool id of the user pool where the already user exists>',
            Username=event['userName']
        )
        if (user):
            for userAttribute in user['UserAttributes']:
                if userAttribute['Name'] == 'email':
                    userEmail = userAttribute['Value']
                    print(userEmail)
                    event['response']['userAttributes'] = {
                        "email": userEmail,
                        "email_verified": "true"
                    }
            event['response']['messageAction'] = "SUPPRESS"
            
            print (event)
            return (event)
        else:
            return('Bad Password')
            
    else:
        return('there was an error')

新しいユーザープールにユーザー移行トリガーを追加

Amazon Cognito コンソールで、新しい Lambda 関数をユーザー移行 Lambda トリガーとして設定します。詳細については、ユーザープールの Lambda トリガーの追加を参照してください。

ユーザー移行のために USER_PASSWORD_AUTH フローを有効化

移行時に USER_PASSWORD_AUTH 認証フローを使用するようにユーザープールアプリクライアントを設定します。これにより、アプリがユーザーのユーザー名とパスワードを Lambda 関数に渡した後に、既存のユーザープールから認証を行うことができます。

ユーザーが古いユーザープールに存在し、新しいユーザープールには存在しない場合のサインイン試行に対して、デフォルトの認証フローを USER_PASSWORD_AUTH フローに変更するロジックをアプリに追加します。

たとえば、アプリが JavaScript を使用している場合は、cognitoUser.setAuthenticationFlowTypeUSER_PASSWORD_AUTH に指定します。

注意: ユーザーの移行が完了すると、アプリの認証フローを USER_SRP_AUTH に変更することをお勧めします。このフローでは、ネットワークを介してパスワードを送信することなく、セキュアリモートパスワード (SRP) プロトコルを使用してユーザーを認証します。このフローは、USER_PASSWORD_AUTH フローよりもセキュリティ上の利点があります。詳細については、ユーザー移行認証フローおよびユーザープールを使用した認証を参照してください。

cognitoUser.setAuthenticationFlowType('USER_PASSWORD_AUTH');

    cognitoUser.authenticateUser(authenticationDetails, {
        onSuccess: function(result) {
            // User authentication was successful
        },
        onFailure: function(err) {
            // User authentication was not successful
        },
        mfaRequired: function (codeDeliveryDetails) {
            // MFA is required to complete user authentication.
            // Get the code from user and call
            cognitoUser.sendMFACode(verificationCode, this);
        }
    });

詳細については、例: Lambda トリガーを使用した JavaScript ユーザーの移行を参照してください。

セットアップをテストする

Amazon Cognito のホストされたウェブ UI を使用してアプリにサインインし、認証フローをテストします。サインインしたユーザーは、新しいユーザープールで認証した後に移行されます。

注意: テスト用にサインインするユーザーアカウントがない場合は、新しいユーザーを作成してください。

トラブルシューティング

テスト中に「ユーザーの移行中に例外が発生しました」などのエラーメッセージが表示される場合は、Lambda のログステートメントを有効にしてください。これにより、ユーザー移行 Lambda トリガーのパラメータAmazon CloudWatch Logs に記録されます。

エラーを再現してから、ユーザー移行 Lambda トリガー内のパラメータまたは構文エラーに関する問題についてログを確認してください。