Cognito change phone_number before confirm via Phone

Viewed 4355

I want to change phone_number attribute of user before they confirm via phone. My flow step:

  1. User register by username, password, and phone number

  2. User must be enter confirmation code received by the phone. In this step user want to change the phone number (wrong number or change the phone...)

2.1 In case the 1st phone number be wrong, the next phone number is correct -> only one confirmation code had been sent -> it works!

2.2 In case the 1st phone number and the next are correct -> have two confirmation code had been sent(1st - xxx, 2nd - yyy) -> User enter 2nd confirmed code, Cognito throws CodeMismatchException: Invalid verification code provided, please try again. error. User enter 1st code, user had been confirmed, but in Cognito system the user has phone_number is 2nd number and phone_number_verified is true.

I use adminUpdateUserAttributes to change phone_number of a user who has status is UNCONFIRMED. Confirmation code auto send after me call change phone number.

How to fix this?

!!!Update

Currently, I removed the feature User can update their phone_number before they confirmed via phone from my application.

It takes me about 5 days, I just want to memo my case.

When you try to update phone_number (or email) attribute, Cognito will send a confirmation to your phone (or email) in automatically, this is the first code - (1st - xxx), the code to confirm your new attribute value (not for user confirmation).

In the same time, logic code calls resendConfirmationCode function, it send the second code - (2nd - yyy), this is main reason only the second code working (we use confirmSignUp function to handle the code).

3 Answers

For anybody else seeking the answer to this, what I ended up doing was writing a lambda that essentially checks if a user is unconfirmed, delete's the user and then signs them up again. I originally went the updateUserAttributes route but it felt insecure in case a bad actor got access to the lambda and updated a confirmed users phone number to theirs. If a user signups with a different username but the same number from a different account, it will invalidate the others users account. Hence the logic below.

try {
            const userParams = {
                UserPoolId: process.env.userpool_id,
                Username: event.args.username
            };
            const { UserStatus } = await identity.adminGetUser(userParams).promise();
            if (UserStatus === 'UNCONFIRMED') {
                const deletedIdentity = await identity.adminDeleteUser(userParams).promise();
                if (deletedIdentity) {
                    const signupParams = {
                        ClientId: process.env.client_id,
                        Password: event.args.password,
                        Username: event.args.password,
                        UserAttributes: [
                            {
                                Name: 'phone_number',
                                Value: event.args.phoneNumber
                            }
                        ]
                    }
                    const newSignUp = await identity.signUp(signupParams).promise();
                    if (newSignUp) {
                        response.send(event, context, response.SUCCESS, {
                            newSignUp
                        });
                        callback(null, newSignUp)
                    }
                }
            } else {
                response.send(event, context, response.ACCESSDENIED, {
                    error: 'User not authorized to perform this action'
                });
                callback({error: 'User not authorized to perform this action'}, null)
            }

        } catch (error) {
            response.send(event, context, response.FAILURE, {
                error
            });
            callback(error, null)
        }
Related