'How can I verify a user attribute in AWS Cognito?

I'm trying to verify a user's email by calling the verifyAttribute method.

I am able to authenticate and get a JWT response - and with that I can do the following:

const { email, phone, accessToken } = verifyUserAttributesDto;
const getUser = await CognitoService.getUser(accessToken);
const attributes = getUser.UserAttributes.reduce(
  (acc, { Name, Value }) => ({ ...acc, [Name]: Value }),
  {},
);

console.log(attributes);

........

{
  sub: '5f04a73b-...',
  email_verified: 'false',
  phone_number_verified: 'false',
  phone_number: '+12222222222',
  given_name: 'First',
  family_name: 'Last',
  email: '[email protected]'
}

So I know I'm able to access the user.

Later I do:

const cognitoUser = new AmazonCognitoIdentity.CognitoUser({
      Username: attributes.email,
      Pool: this.userPool,
    });

...

CognitoUser {
  username: '[email protected]',
  pool: CognitoUserPool {
  ...

I believe I have an instance of a CognitoUser here, but maybe I don't; maybe that's the problem.

If I do:

return new Promise(function (resolve, reject) {
    return cognitoUser.verifyAttribute(attribute, accessToken, {
        onSuccess: (success) => {
            console.log(success);
            resolve(success);
        },
        onFailure: (err) => {
            console.log(err);
            reject(err);
          },
        });
    });

The response I get back is:

ERROR [ExceptionsHandler] User is not authenticated

I have verified in the AWS console that the confirmation status for the user is confirmed and the account status is enabled.

If I've got a valid JWT, and am able to "get" the user, why am I getting that error?



Solution 1:[1]

It's painfully obvious I'm not sure what I'm doing. I got this working due to:

  1. I wasn't providing the verification code
  2. I was using the wrong identity provider (cognito vs. cognito user)

There are two methods needed to verify:

  • getUserAttributeVerificationCode
  • verifyUserAttribute
async getUserAttributeVerificationCode(
    attribute: string,
    accessTokenDto: AccessTokenDto,
  ) {
    const { accessToken } = accessTokenDto;

    const cognito = new AWS.CognitoIdentityServiceProvider();

    try {
      return await cognito
        .getUserAttributeVerificationCode({
          AccessToken: accessToken,
          AttributeName: attribute,
        })
        .promise();
    } catch (err) {
      throw new BadRequestException(err.message);
    }
  }
async verifyUserAttribute(verifyUserAttributesDto: VerifyUserAttributesDto) {
    const { email, phone, accessToken, verificationCode } =
      verifyUserAttributesDto;

    const cognito = new AWS.CognitoIdentityServiceProvider();

    try {
      if (email || phone) {
        const attribute = email ? 'email' : 'phone';

        return await cognito
          .verifyUserAttribute({
            AccessToken: accessToken,
            AttributeName: attribute,
            Code: verificationCode,
          })
          .promise();
      }
    } catch (err) {
      throw new BadRequestException(err.message);
    }
  }

You'll first need to call getUserAttributeVerificationCode with a valid JWT. You'll then get sent a verification code (email/sms).

With that, you'll call verifyUserAttribute with all of the proper attributes.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 DharmanBot