In our project, we use AWS Cognito user pools to sign-up and sign in our users. With the earlier versions of AWS Cognito, the usernames/email addresses used in the pool were case-sensitive. This meant that when a user signed up with Name@acme.com and later tried to sign in with name@acme.com it failed, leaving the user behind in total confusion thinking he typed the password wrong or something.
Newer versions of AWS Cognito user pools luckily support setting the case insensitivity, but this only applies for newly created pools. So, what do you do with your legacy pool with x-thousand users? Luckily, there is a way to migrate your users – together with group memberships and passwords (!)- to the new user pool! Below I describe how I did it for our situation, allowing a seamless migration of our users to the new user pool. The users won’t even notice that they are migrated!
Take care though, test and retest! Your mileage may vary!
Basic flow
- User tries to authenticate against new pool, initialy this user is not found and that will trigger the User Migration trigger.
- This trigger needs to return the user data with it’s properties filled in (email, password, etc)
- The user is created in the new pool.
- The PostAuthentication trigger will take care of adding the original groups to this user in the new pool
- The user is logged in
I coded the Lambda triggers in Python. Code is in my GitHub repo.
How to
- Create a new Cognito user pool. All users from the ‘old’ cognito pool will end up in this new pool.
- For both pools: Go to App Clients and
- set “Enable username password auth for admin APIs for authentication (ALLOW_ADMIN_USER_PASSWORD_AUTH)” to active
- set “Enable username password based authentication (ALLOW_USER_PASSWORD_AUTH)” to active
- If you have many groups, maybe remove the ‘#’ sign in main.py before ‘initializeGroups(event, context)’ so the groups are created for you. I only had 3 groups, so i created them by hand in the new pool.
- Create a new lambda function
- Choose: from scratch,
- Choose Python 3.9, press Create
- In the source, choose Upload from zip
- You can upload a zip file container all *.py files from the github link below
- In Runtime settings, set Handler to main.Handler
- Change constant.py to the old/new pool info
- Create a new policy to allow the lambda to perform actions on the Cognito user pool. See iam-cognito-policy.json for inspiration
- Go to Policy Usage tab
- Click Attach, attach the (automatically created) lamda role to this policy
- Go to the new Cognito user pool, and attach the lamda in Post authentication and User Migration triggers.
- Change your client / front end app to use the new cognito user pool. I needed to change the authenticationFlowType in amplify.config.ts from ‘USER_SRP_AUTH’ to ‘USER_PASSWORD_AUTH’
This allows the password to be saved for the user in the new pool. - Test with an existing user and a new user
Good luck!
PS1: the new version of Cognito allows you to also set the email verification message (besides the user invitation message that was already possible in the old Cognito). So one more reason to upgrade your user pool !
PS2: after all your users are migrated (did log in once), it’s wise to disable/remove the triggers from the new Cognito pool.
Give me tha code !
https://github.com/rwijngaa/aws-cognito-migrate
Used info:
https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-migrate-user.html
Thanks, Rino for this amazing code. however, it still not migrating the users and not checking the old pool. Do you have a test script for this lambda function to see if it’s working or is there any way i can troubleshoot what is wrong with it?
Thanks in advance
Hi, no test for the lambda yet. Cloudwatch (logging) is your friend for now 😉