skip to Main Content

I am using Cognito user pools to create and authentication system.

Everything works perfectly. However, there is one scenario that I cannot figure out a solution for.

When a user signs up, a confirmation code is sent to the user’s email.
Let’s say the user accidentally closed the tab and tried signing up with the same email. Then, an error message will show up stating that the user already exists. If the users heads to the log in page and logs in using his email. An error shows up stating that the user is not confirmed.

Basically, the user is stuck.

My question is, how can a user confirm their email if the current sign up page was closed? How can I redirect the user to a confirmation page?

2

Answers


  1. I came accross the exact same problem. The only but simple solution I found is to change the verification type from code to link. This is done within the verifcation message settings under messaging.

    After doing that the user does not get a code anymore, instead he gets a link to click on. When he later comes back to the log in page, he is confirmed already and can enter his credentials right away.

    Login or Signup to reply.
  2. I used Cognito triggers to solve this problem.

    So the solution is to write a pre-authentication lambda function which triggers when user try to sign-in.

    The lambda function looks like this

        const {
        CognitoIdentityProvider,
        UserStatusType,
      } = require("@aws-sdk/client-cognito-identity-provider");
      
      exports.handler = async (event, context, callback) => {
        const cognitoIdp = new CognitoIdentityProvider();
        
        const params = {
          UserPoolId: event.userPoolId,
          Filter: 'email = "' + event.request.validationData.Username + '"',
        };
      
        const { Users: users } = await cognitoIdp.listUsers(params);
      
        if (users && users.length > 0) {
          // User exists
          const user = users[0];
      
          if (user.UserStatus === UserStatusType.UNCONFIRMED) {
            throw Error("USER_UNCONFIRMED");
          }
          const emailVerifiedAttribute = user.Attributes.find(
            (attr) => attr.Name === "email_verified"
          );
      
          if (emailVerifiedAttribute && emailVerifiedAttribute.Value === "false") {
            throw Error("EMAIL_NOT_VERIFIED");
          }
        }
        return event;
      };
    

    This helps a user to know whether the user exists in Cognito user pool and they are not confirmed.

    This exception can be tracked like this

        const onError = (err) => {
        if (err instanceof Error) {
          let msg;
          switch (err.name) {
            case 'UserLambdaValidationException':
              if (err.message.includes('USER_UNCONFIRMED')) {
                msg = 'User not confirmed, Redirecting to verification page';
               //Add logic to redirect to verification page and resend code
              } else {
                msg = 'Something went wrong, Please try again later';
              }
              break;
            default:
              msg = err.message;
              break;
          }
        }
      };
    

    With this info we can redirect our page to confirmation page and use Cognito’s resendConfirmationCode method to send the verification code.

      export async function resendCode(username) {
      return new Promise((resolve, reject) => {
        const cognitoUser = getCognitoUser(username);
        cognitoUser.resendConfirmationCode((err, res) => {
          if (err) {
            reject(err);
          } else {
            resolve(res);
          }
        });
      });
    }
    

    This helps to confirm the Cognito user.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search