Z_z_Z
Z_z_Z

Reputation: 1107

AWS Cognito Authentication Returns Error - Javascript SDK

I am using AWS Cognito to authenticate users in a new app that I am building.

I am using the amazon-cognito-identity-js library in my project (link to Github: https://github.com/aws-amplify/amplify-js/tree/master/packages/amazon-cognito-identity-js). Since users in this particular user pool cannot sign themselves up - I sign them up manually - I know that I need "Use case 23" as stated in the README.md from Github.

So my code is as follows:

    ...
    const userPoolData = {
        UserPoolId: <MY_USER_POOL_ID>,
        ClientId: <MY_CLIENT_ID>
    };

    const userPool = new CognitoUserPool(userPoolData);

    const authenticationData = {
        Username: email,
        Password: tempPassword
    };
    const userData = {
        Username: email,
        Pool: userPool
    }

    const authenticationDetails = new AuthenticationDetails(authenticationData);
    const cognitoUser = new CognitoUser(userData);

    cognitoUser.authenticateUser(authenticationDetails, {
        onSuccess: (result) => {
            console.log(result);
        },
        onFailure: (err) => {
            console.log("Error from cognito auth: ", err);
        },
        newPasswordRequired: (userAttributes) => {
            delete userAttributes.email_verified;
            cognitoUser.completeNewPasswordChallenge(newPassword, userAttributes, this);
        }
    })
    ...

When I execute this code, I successfully confirm my user. I can see this in the AWS Cognito console. However, instead of receiving the result object, I get an error in the javascript console on the client that says:

Uncaught (in promise) TypeError: Cannot read property 'onFailure' of undefined
    at eval (CognitoUser.js:572)
    at eval (Client.js:108)

But when I attempt to sign in with the newPassword in place of the tempPassword previously sent, I am now able to successfully get the resultobject with the three tokens all present.

So I know that everything is kinda working, but isn't what I am expecting.

What is causing this error? How can I fix it? I want to receive the result object immediately when the user first signs in with the tempPassword and their newPassword so that they can start using the app.

EDIT:

Thinking that I had to retrieve the userAttributes myself was a mistake. The newPasswordRequired function passes them automatically. So I updated my code above to go with "Use case 23" as presented on Github.

But now I get a slightly different error than before:

Uncaught (in promise) TypeError: callback.onFailure is not a function
    at eval (CognitoUser.js:572)
    at eval (Client.js:108)

Everything still works as far as Cognito is concerned, but there must be something wrong with my onFailure function, which is very strange.

Any thoughts?

Thanks in advance

Upvotes: 5

Views: 8597

Answers (2)

Z_z_Z
Z_z_Z

Reputation: 1107

Alright, I solved it. The issue was that I was using ES6 arrow functions. As Apolozeus pointed out, I needed to pass this into the cognitoUser.completeNewPasswordChallenge function. But due to the way ES6 behaves, this was returning undefined. So, changing my cognitoUser.authenticateUser function to the following solved everything:

  cognitoUser.authenticateUser(authenticationDetails, {
        onSuccess: function (result) {
            resolve(result.getAccessToken().getJwtToken());
        },
        onFailure: function (err) {
            console.log("Error from cognito promise: ", err);
            reject(err);
        },
        newPasswordRequired: function (userAttributes) {
            delete userAttributes.email_verified;
            cognitoUser.completeNewPasswordChallenge(newPassword, userAttributes, this);
        }
    })

I'm going to play around with the amazon-cognito-identity-js library a bit and see if I can get ES6 arrow functions to work here. It's really annoying to have to work around that.

Shout out to Apolozeus for the help

Upvotes: 11

sayboras
sayboras

Reputation: 5165

Please update the line cognitoUser.completeNewPasswordChallenge(newPassword, userAttributes); into cognitoUser.completeNewPasswordChallenge(newPassword, userAttributes, this) Basically, this will make sure the callback function within the same object.

Upvotes: 2

Related Questions