How do I change the attributes of an Amazon Cognito user pool after creation?

6 minute read
0

I created an Amazon Cognito user pool and now I want to change the standard attributes required for user registration.

Short description

You can't change standard user pool attributes after a user pool is created. Instead, create a new user pool with the attributes that you want to require for user registration. Then, use an AWS Lambda function as a user migration trigger to migrate existing users to the new user pool.

Note: You can add custom attributes to an existing user pool, but these attributes aren't required for user registration.

Resolution

Set up a new user pool with different attributes

Create a new user pool. Then, before you choose Create pool, edit the standard attributes to your preference.

Important: If you specify new required attributes in the user pool, then design your Lambda function to provide these new attributes to the new user pool. If you don't design the function to provide the new attributes, then authentication fails during user migration. For example, suppose your old user pool required only email, but your new user pool requires both email and phone number. In this case, pass attribute values for phone number to your new user pool to successfully authenticate users.

Create a Lambda function

To create a user migration Lambda function, use the Lambda console editor or build and upload your own deployment package.

Important: This example code doesn't work to migrate users that use multi-factor authentication (MFA) in the old user pool.

To test your configurations, use the following example function in Python:

# 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')

Note: Replace UserPoolId with the ID of the old user pool. Find the ID in the Amazon Cognito console, on the management page for the user pool, on the General settings tab. Replace ClientId with the app client ID of the old user pool. Find the app client ID in the Amazon Cognito console under App clients.

Add a user migration trigger to the new user pool

In the Amazon Cognito console, set your new Lambda function as a user migration Lambda trigger. For more information, see Adding a user pool Lambda trigger.

Turn on the USER_PASSWORD_AUTH flow for user migration

Configure your user pool app client to use the USER_PASSWORD_AUTH authentication flow at the time of migration. This authentication flow lets your app pass the user's user name and password to the Lambda function. The authentication flow can then authenticate the user from the existing user pool.

Add logic to your app to change the default authentication flow to the USER_PASSWORD_AUTH flow. Have the logic change the authentication flow for sign-in attempts where the user exists in the old user pool but not the new user pool.

For example, if your app uses JavaScript, specify cognitoUser.setAuthenticationFlowType as USER_PASSWORD_AUTH.

Note: After your users are migrated, it's a best practice to change your app's authentication flow to USER_SRP_AUTH. This flow uses the Secure Remote Password (SRP) protocol to authenticate users without the need to send passwords across the network. This flow also provides security benefits over the USER_PASSWORD_AUTH flow.

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

Test the setup

Use the Amazon Cognito hosted web UI to sign in to your app and test the authentication flow. The user that you sign in with is authenticated with the new user pool and then migrated.

Note: If you don't have a user account to sign in with to test your configurations, then create a new user.

Troubleshoot issues

If you get an error message while you test, such as "Exception during user migration", then turn on logging statements from Lambda. This setting logs the parameters for a user migration Lambda trigger to Amazon CloudWatch logs. Reproduce the error, then review the logs for any issues with the parameters or syntax errors in the user migration Lambda trigger.

Related information

Customizing user pool workflows with Lambda triggers

What's the difference between Amazon Cognito user pools and identity pools?

User pools

AWS OFFICIAL
AWS OFFICIALUpdated a month ago
2 Comments

How can this be done with CloudFormation?

replied 3 months ago

Thank you for your comment. We'll review and update the Knowledge Center article as needed.

profile pictureAWS
MODERATOR
replied 3 months ago