Amazon-cognito-identity-js: User does not exist.

Created on 24 May 2017  路  8Comments  路  Source: amazon-archives/amazon-cognito-identity-js

Is it not possible to use aliases with this? I was under the impressions aliases allow the user to authenticate with more than just preferred_username. in my case phone and email -- but both those give me

cognito.js:129 Failed To Authenticate User: User does not exist.

Most helpful comment

Whilst I think that it would be better if the decision to require verification lied with the application developer (i.e us), I got around this by creating this lambda function and assigning it as a pre sign up trigger to my user pool.

The function will first check that the email address doesn't exist. The reason for this is that at sign up, AWS automatically reassigns email addresses when using them as aliases. I'd nearly consider this a security vulnerability (as if you don't actively protect against it, anyone can create an account with your email address and effectively steal your email address), and a strange design choice for a login system (where emails are generally ALWAYS only ever associated with one account), but I'm sure there were logical reasons to do so. Probably to allow for other auth flows I've not considered -- and at the end of the day, Cognito allows the user flow we're wanting in this thread, we just have to do a bit more work to get it, as you'll see below.

In the below, if the email exists, the sign up will not succeed. If it doesn't exist, the email address is automatically marked as verified, the user account marked as confirmed, and the user can now be logged in (or auto logged in in my case).

Note that if you want to track whether a user has actually ever verified their email address manually (i.e you sent a confirmation email), you'll have to add a custom attribute in order to track that, as we have to "hack" the existing one in order to allow users to sign in without verification (which in the real world, is always a request from the business as they want to get people into the app with as less friction as possible. You can always ask for verification later on before the user performs any actual critical operations).

Hope this helps.

const Aws = require('aws-sdk');
const cognitoIdentityService = new Aws.CognitoIdentityServiceProvider({region: 'ap-southeast-2'});

exports.handler = (event, context, callback) => {
    const params = {
        "UserPoolId": event.userPoolId,
        "Filter": `email = \"${event.request.userAttributes.email}\"`,
        "Limit": 1
    };

    cognitoIdentityService.listUsers(params, (err, data) => {
        if (!err) {
            if(data.Users && data.Users.length > 0) {
                // We check if the email exists because otherwise, when the email is verified, if it already
                // belongs to another account as an aliases, then Cognito will automatically reassign
                // the alias to this new account, which would be a disaster to the login system.
                var error = new Error('This email address is already associated with another user');
                context.done(error, event);
            } else {
                event.response.autoConfirmUser = true;
                event.response.autoVerifyEmail = true;
                context.done(null, event);
            }

        } else {

            var error = new Error('There was an error in the Cognito pre sign up lambda trigger: ' + JSON.stringify(err));
            context.done(error, event);
        }
    });
};

All 8 comments

Yes, if you enable the particular alias in the console it should allow you to login using the alias.

I had this issue. Just for historical purposes, if you're using an alias like phone_number or email, make sure that the alias is verified (phone_number_verified or email_verified) before using it. If the alias isn't verified, you must use username, otherwise you'll get UserNotFoundException in Cognito User Pools.

This ticket should be re-opened. This is an issue. Yes, it is true that if you are using an alias like phone_number and/or email you have to first verify that the alias is verified before using a signin handler such as AuthenticationHandler. But you cannot verify the attributes without signing in. In other words, how can you tell when to get user with email or when to get user by username?

CognitoUser user = userPool.getUser(email) or CognitoUser user = userPool.getUser(username)

This is an issue and really should be changed to ALWAYS accept an email even if using alias.

@drxeno02 I agree with you. But the lack of support from Amazon makes this product the worst one ever.

A quick tip: try Firebase Authentication from Google. Integration is faster and easier.

@drxeno02 Below are some insight that may help you get going:

  1. When user Signs up, user can verify the email or phone_number at the time of confirm sign up. This would automatically allow the user to use email or phone_number as alias.
  2. If user does not verify at the time of signup, developer has an option to verify the alias. Developer can call AdminUpdateUserAttributes to call verify email / phone_number.
  3. Cognito launched new simplified aliases which creates the alias for the email and phone_number irrespective of the whether they are verified or not. Developer can select this option while creating the user-pool. User will be able to sign-in using email and phone_number even without verifying them.

I have tried logging in using an email with Require Verification enabled and email_verified=true on the user. And also with Require Verification disabled.

For both I get UserNotFoundException: User does not exist.

So, there's no way to initiateAuth with email only?

It works if I use the random generated string e.g "3d552cac-0df6-4c9d-91a0-550f5f4cccd5" from the Cognito aws console - but this isn't really working as expected

While creating userpool, there is an option to select for 'How do you want your end users to sign in?'. For this header, if 'Email address or phone number' is selected, users are allowed to signin using email address or phone number without verifying them.

Please try out this option, this should allow initiateAuth with email address.

Whilst I think that it would be better if the decision to require verification lied with the application developer (i.e us), I got around this by creating this lambda function and assigning it as a pre sign up trigger to my user pool.

The function will first check that the email address doesn't exist. The reason for this is that at sign up, AWS automatically reassigns email addresses when using them as aliases. I'd nearly consider this a security vulnerability (as if you don't actively protect against it, anyone can create an account with your email address and effectively steal your email address), and a strange design choice for a login system (where emails are generally ALWAYS only ever associated with one account), but I'm sure there were logical reasons to do so. Probably to allow for other auth flows I've not considered -- and at the end of the day, Cognito allows the user flow we're wanting in this thread, we just have to do a bit more work to get it, as you'll see below.

In the below, if the email exists, the sign up will not succeed. If it doesn't exist, the email address is automatically marked as verified, the user account marked as confirmed, and the user can now be logged in (or auto logged in in my case).

Note that if you want to track whether a user has actually ever verified their email address manually (i.e you sent a confirmation email), you'll have to add a custom attribute in order to track that, as we have to "hack" the existing one in order to allow users to sign in without verification (which in the real world, is always a request from the business as they want to get people into the app with as less friction as possible. You can always ask for verification later on before the user performs any actual critical operations).

Hope this helps.

const Aws = require('aws-sdk');
const cognitoIdentityService = new Aws.CognitoIdentityServiceProvider({region: 'ap-southeast-2'});

exports.handler = (event, context, callback) => {
    const params = {
        "UserPoolId": event.userPoolId,
        "Filter": `email = \"${event.request.userAttributes.email}\"`,
        "Limit": 1
    };

    cognitoIdentityService.listUsers(params, (err, data) => {
        if (!err) {
            if(data.Users && data.Users.length > 0) {
                // We check if the email exists because otherwise, when the email is verified, if it already
                // belongs to another account as an aliases, then Cognito will automatically reassign
                // the alias to this new account, which would be a disaster to the login system.
                var error = new Error('This email address is already associated with another user');
                context.done(error, event);
            } else {
                event.response.autoConfirmUser = true;
                event.response.autoVerifyEmail = true;
                context.done(null, event);
            }

        } else {

            var error = new Error('There was an error in the Cognito pre sign up lambda trigger: ' + JSON.stringify(err));
            context.done(error, event);
        }
    });
};
Was this page helpful?
0 / 5 - 0 ratings

Related issues

kpitzen picture kpitzen  路  3Comments

johnf picture johnf  路  3Comments

howardya picture howardya  路  3Comments

tranan89 picture tranan89  路  5Comments

m-schrepel picture m-schrepel  路  6Comments