Amazon Cognito 사용자 풀을 생성한 후 해당 속성을 변경하려면 어떻게 해야 합니까?

최종 업데이트 날짜: 2019년 6월 24일

Amazon Cognito 사용자 풀을 생성했습니다. 그리고 이제 사용자 등록에 필요한 표준 속성을 변경하려고 합니다. 속성을 변경하려면 어떻게 해야 합니까?

간략한 설명

사용자 풀을 생성한 후에는 표준 사용자 풀 속성을 변경할 수 없습니다. 대신, 사용자 등록에 필요한 속성을 사용하여 새 사용자 풀을 생성합니다. 그런 다음, AWS Lambda 함수를 사용자 마이그레이션 트리거로 사용하여 새 사용자 풀에 기존 사용자를 마이그레이션합니다.

참고: 기존 사용자 풀에 사용자 정의 속성을 추가할 수 있지만, 이러한 속성은 사용자 등록에 대한 필수 속성이 아닙니다.

해결 방법

다른 속성으로 새 사용자 풀 설정

새 사용자 풀을 생성합니다. 그런 다음, 설정 중 마지막에 [풀 생성]을 선택하기 전에 기본 설정에서 표준 속성을 편집합니다.

중요: 사용자 풀에서 새로운 필수 속성을 지정하는 경우 새 사용자 풀에 이러한 새 속성을 제공하도록 Lambda 함수를 설계해야 합니다. 그렇지 않으면 사용자 마이그레이션 중에 인증에 실패합니다. 예를 들어, 이전 사용자 풀에서 email만 필요하지만, 새 사용자 풀에서는 emailphone number 둘 다 필요하다고 가정합니다. 이 경우 사용자를 성공적으로 인증하려면 phone number의 속성 값을 새 사용자 풀로 전달해야 합니다.

Lambda 함수 생성

Lambda 콘솔 편집기를 사용하거나 자체 배포 패키지를 구축 및 업로드하여 사용자 마이그레이션 Lambda 함수를 생성합니다.

다음은 테스트용으로 사용할 수 있는 Python 형식의 함수 예제입니다.

참고: UserPoolId의 경우 예제 값을 이전 사용자 풀 ID로 대치합니다. 이 ID는 Amazon Cognito 콘솔에서 사용자 풀의 관리 페이지, [일반 설정] 탭에서 확인할 수 있습니다. 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 인증 흐름을 사용하도록 사용자 풀 앱 클라이언트를 구성합니다. 그러면 앱은 사용자의 사용자 이름과 암호를 전달하고 기존 사용자 풀에서 이를 인증할 수 있습니다.

사용자가 이전 사용자 풀에 존재하고 새 사용자 풀에 존재하지 않는 로그인 시도에 대해 기본 인증 흐름을 USER_PASSWORD_AUTH 흐름으로 변경하는 로직을 앱에 추가합니다.

예를 들어, 앱에서 JavaScript를 사용하는 경우 USER_PASSWORD_AUTHcognitoUser.setAuthenticationFlowType을 지정합니다.

참고: 사용자를 마이그레이션한 후에는 앱의 인증 흐름을 USER_SRP_AUTH로 변경하는 것이 모범 사례입니다. 이 흐름은 네트워크에서 암호를 전송하지 않고도 SRP(Remote Password) 프로토콜을 사용하여 사용자를 인증합니다. 또한 이 흐름은 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를 사용하여 앱에 로그인하고 인증 흐름을 테스트합니다. 로그인한 사용자는 새 사용자 풀에서 인증된 후에 마이그레이션됩니다.

참고: 테스트를 위해 로그인하려는 사용자 계정이 없으면 새 사용자를 생성합니다.

문제 해결

테스트하는 동안 "Exception during user migration"과 같은 오류 메시지가 나타나면 Lambda에서 로깅 명령문을 활성화합니다. 그러면 사용자 마이그레이션 Lambda 트리거의 파라미터Amazon CloudWatch Logs에 기록합니다.

오류를 재현하고 사용자 마이그레이션 Lambda 트리거에 파라미터나 구문 오류와 관련된 문제가 있는지 로그를 검토합니다.