50

How do I go about email verifying a user who is CONFIRMED yet email_verified is false?

The scenario is roughly an agent signs up user on their behalf, and I confirm the user through the admin call adminConfirmSignUp. At that point, the user cannot change their password because of the email_verified flag being false.

I can't call resendConfirmationCode because the user is already confirmed.

I can't call forgotPassword because the email_verified flag is false.

The best I can think of is deleting the user account and calling signUp (prompting them to re-enter their password or a new password), hence recreating their account.

user1432403
  • 1,533
  • 4
  • 16
  • 21

8 Answers8

72

Using the AWS CLI you can update the email_verified attribute:

aws cognito-idp admin-update-user-attributes 
--user-pool-id eu-west-xxxxxx 
--username xxxxyyyy@example.com
--user-attributes Name=email_verified,Value=true

Here is the official documentation: https://awscli.amazonaws.com/v2/documentation/api/latest/reference/cognito-idp/admin-update-user-attributes.html

otmezger
  • 10,410
  • 21
  • 64
  • 90
LiorH
  • 18,524
  • 17
  • 70
  • 98
36

You can change email_verified, phone_number_verified and other attributes by calling adminUpdateUserAttributes without any lambdas and triggers:

'use strict'

var AWS = require('aws-sdk')

AWS.config.update({
  accessKeyId: 'YOUR_ACCESS_KEY_HERE',
  secretAccessKey: 'YOUR_SECRET_ACCESS_KEY_HERE',
  region: 'us-east-1' // change region if required
});

var CognitoIdentityServiceProvider = AWS.CognitoIdentityServiceProvider

var client = new CognitoIdentityServiceProvider({
  apiVersion: '2016-04-19',
  region: 'us-east-1' // change region if required
})

client.adminUpdateUserAttributes({
  UserAttributes: [{
      Name: 'phone_number_verified',
      Value: 'true'
    }, {
      Name: 'email_verified',
      Value: 'true'
    }
    // other user attributes like phone_number or email themselves, etc
  ],
  UserPoolId: 'COGNITO_USER_POOL_ID_HERE',
  Username: 'USERNAME'
}, function(err) {
  if (err) {
    console.log(err, err.stack)
  } else {
    console.log('Success!')
  }
})
aring
  • 3,422
  • 2
  • 22
  • 29
  • I can confirm this works. Unfortunately, Cognito doesn't call my "Post confirmation" trigger though, but that's a different problem I guess. – Ryan Shillington Mar 29 '17 at 23:12
  • 1
    @RyanShillington, you are correct, "Post confirmation" trigger fires when user status became `CONFIRMED`. If you want to call your "Post confirmation" trigger also when user attributes changing, even if status already in `CONFIRMED` state (i.e. - calling another lambda from another lambda), you can use SNS topic for that: https://gist.github.com/jeremypruitt/ab70d78b815eae84e037 Just a gist, I am sure that you can find AWS documentation for that. – aring Mar 31 '17 at 13:34
  • Yep this works, I use it after confirming user and then updating the attributes. – Umar Farooque Jul 09 '19 at 16:07
  • The post confirmation trigger does not fire in the circumstances described by the OP where user status is CONFIRMED but email_verified is false. – Matt Saunders Jan 03 '22 at 11:10
12

Currently, Cognito does not allow an external agent to update the email_verified and phone_verified attributes on behalf of the user. The only way these can be marked as true is through a code verification process which can be done by the end user. The exception to this is with admin level APIs, as answers below describe, but those shouldn't be done from client side.

The process is this: user signs-in and gets an access token. They then call GetUserAttrbuteVerificationCode API with the attribute they want to verify. This will deliver a code to the user, which can be used by calling VerifyUserAttribute which will flip the attribute as verified.

Jeff Bailey
  • 5,655
  • 1
  • 22
  • 30
  • 2
    Thanks for the reply, so I gather if the user has lost their password and we're in the CONFIRMED email_verified = false state, the only think I can do is delete their account and create it again. – user1432403 Aug 30 '16 at 18:15
  • Correct. They have to sign in to get the token needed to go through this flow. – Jeff Bailey Aug 30 '16 at 18:16
  • 5
    Is there any plan to get this working? The [docs](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html) indicate that the flag can be set to true when the user is created, and the console sort-of thinks that it's verified (it will show the "Reset Password" button), but actually attempting tor reset the password fails with a "no verified email" error. It seems more than a bit silly (and painful for users) to send them a temporary password via email, then send *another* email in order to verify that their email address is valid. – kdgregory Dec 26 '16 at 23:11
  • 4
    UPDATE: `email_verified` and `phone_number_verified` can be set to `true` using the `AdminUpdateUserAttributes` API, see [this](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateUserAttributes.html) and [this](https://stackoverflow.com/questions/39231797/aws-cognito-user-stuck-in-confirmed-and-email-verified-false/43033722#43033722). – snehanshu.js Jun 16 '20 at 13:19
  • @JeffBailey the client side solution doesnt work as it needs an accesskey and the user is not able to authenticate itself, it keeps on getting usernotconfirmed and doesnt give any tokens. – Swapnil Mhaske Jul 01 '21 at 13:12
11

You can now programmatically set email_verified to true using the Pre-Signup lambda trigger and modifying the returned event with event.response.autoVerifyEmail = true;

It's not in the docs yet but referenced on this github issue. Also read working with cognito lambda triggers.

iflp
  • 1,742
  • 17
  • 25
  • Yes, this works. And one can also set `event.response.autoConfirmUser = true` – ronkot Oct 10 '19 at 05:04
  • 3
    I cannot get this to work after I have linked with ExternalIdentityProvider, both my user and the external account email attributes stay unconfirmed. – tvb Nov 29 '21 at 22:00
4

Here is the Another Approach you can use to create users by Agents. You can Use AdminCreateUser on the Behalf of user. By calling this API user will be created with a temp Password which will be sent to the user Email Address. (i.e. User will be in Force_Change_Password state). Now use RespondToAuthChallenge API to change the Password.

Note: You need to set "email_verified" attribute in attribute List. to make sure user email will be verified.

Here is the Code Example in NodeJS:

var params = {
 UserPoolId: process.env.userPoolId, /* required */
Username: email,//'STRING_VALUE', /* required */
DesiredDeliveryMediums: [
"EMAIL",
/* more items */
],
ForceAliasCreation: false,


 UserAttributes: [{
Name: 'email_verified',
Value: 'True'
},/* any other Attributes*/],
   };
cognitoidentityserviceprovider.adminCreateUser(params, function (err, data) {
 if (err) {
  console.log(err, err.stack);
  reject(err); // an error occurred
 }
 else {
  console.log(data);
   resolve(data);
 }// successful response 
});
 });
Kashif Ali
  • 91
  • 5
  • 1
    This will give you an error message: 'No email provided but email_verified was true', code: 'InvalidParameterException', You have to provide the 'email' attribute to get this working. – Shiyas Nov 30 '20 at 07:44
4

It was giving an error message: 'No email provided but email_verified was true', code: 'InvalidParameterException'.

So I added also email attribute into attributes list.

const params = {
  UserPoolId: this.userPoolId /* required */,
  Username: username /* required */,
  TemporaryPassword: password,
  DesiredDeliveryMediums: ['EMAIL'],
  ForceAliasCreation: false,
  UserAttributes: [
    {
      Name: 'email_verified' /* required */,
      Value: 'true',
    },
    {
      Name: 'email' /* required */,
      Value: email,
    },
  ],
};

then create the user with these params

cognitoidentityserviceprovider.adminCreateUser(
    params,
    (err, data) => {
      console.log(data);
      if (err) {
        console.log(err);
        reject(err);
        throw new BadRequestException(err);
      }
      // an error occurred
      else resolve(data); // successful response
    },
  );
het
  • 781
  • 9
  • 16
1

Trigger on pre-registration this lambda function (Node.js v6):

exports.handler = function(event, context) {
 event.response.autoConfirmUser = true;
 event.response.autoVerifyEmail = true;
 event.response.autoVerifyPhone = true;
 context.done(null, event);
};

Using the "Configure test event" you can test it first with this payload

{
  "version": 1,
  "triggerSource": "PreSignUp_SignUp",
  "region": "<region>",
  "userPoolId": "<userPoolId>",
  "userName": "<userName>",
  "callerContext": {
      "awsSdk": "<calling aws sdk with version>",
      "clientId": "<apps client id>"
  },
  "request": {
      "userAttributes": {
          "email": "usertestsns06@yopmail.com"
       },
      "validationData": {
          "k1": "v1",
          "k2": "v2"
       }
  },
  "response": {
        "autoConfirmUser": false,
        "autoVerifyEmail": false,
        "autoVerifyPhone": false
  }
}

Now when you create the user from the API those verifications flags should be true.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
panchicore
  • 11,451
  • 12
  • 74
  • 100
-1

verify user email on aws cognito with python using boto3

response =client.get_user_attribute_verification_code(AccessToken='eyJraWQiOiJtTEM4Vm......',AttributeName='email')

response = client.verify_user_attribute( AccessToken='eyJraWQiOiJtTEM......', AttributeName='email', Code='230433')

Here is the Official Documentation. https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cognito-idp.html

Vinod Kumar
  • 29
  • 1
  • 5