amazon-archives / aws-cognito-angular-quickstart

An Angular(v5)-based QuickStart single-page app utilizing Amazon Cognito, S3, and DynamoDB (Serverless architecture)
https://cognito.budilov.com
Apache License 2.0
689 stars 304 forks source link

InvalidParameterException: Invalid attributes given, given_name is missing #116

Closed im1dermike closed 6 years ago

im1dermike commented 6 years ago

After creating a new user through the AWS dashboard and then trying to log into my app with the emailed password, I get the error in the subject when I try to set a new password using the code below (from this library):

newPassword(newPasswordUser: NewPasswordUser, callback: CognitoCallback): void {
        console.log(newPasswordUser);
        // Get these details and call
        //cognitoUser.completeNewPasswordChallenge(newPassword, userAttributes, this);
        let authenticationData = {
            Username: newPasswordUser.username,
            Password: newPasswordUser.existingPassword,
        };
        let authenticationDetails = new AuthenticationDetails(authenticationData);

        let userData = {
            Username: newPasswordUser.username,
            Pool: this.cognitoUtil.getUserPool()
        };

        console.log("UserLoginService: Params set...Authenticating the user");
        let cognitoUser = new CognitoUser(userData);
        console.log("UserLoginService: config is " + AWS.config);
        cognitoUser.authenticateUser(authenticationDetails, {
            newPasswordRequired: function (userAttributes, requiredAttributes) {
                // User was signed up by an admin and must provide new
                // password and required attributes, if any, to complete
                // authentication.

                // the api doesn't accept the email verified field back
                delete userAttributes.email_verified;
                cognitoUser.completeNewPasswordChallenge(newPasswordUser.password, requiredAttributes, {
                    onSuccess: function (result) {
                        callback.cognitoCallback("", userAttributes);
                    },
                    onFailure: function (err) {
                        callback.cognitoCallback(err, null);
                    }
                });
            },
            onSuccess: function (result) {
                callback.cognitoCallback("", result);
            },
            onFailure: function (err) {
                callback.cognitoCallback(err, null);
            }
        });
    }

My instance of NewPasswordUser has all of the attributes I need in Cognito (givenName, familyName, etc.), but they are clearly not being set in the class that gets passed in the AWS call and I don't know where I should manually set them.

jafetmorales commented 6 years ago

I don't think you can set those attributes in the console when you manually create a user. However, you can set them like this using amazon-cognito-identity-js. Just put the given name in there and push it, and remove whatever you don't need:

var AmazonCognitoIdentity = require('amazon-cognito-identity-js');

var poolData = {
    UserPoolId : '*********', // Your user pool id here
    ClientId : '***********', // Your client id here
};
// var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);

var attributeList = [];

var dataEmail = {
    Name : 'email',
    Value : '***********'
};
var dataPhoneNumber = {
    Name : 'phone_number',
    Value : '**********'
};
var dataName = {
    Name : 'name',
    Value : '**********'
};
var dataFamilyName = {
    Name : 'family_name',
    Value : '***********'
};

var attributeEmail = new AmazonCognitoIdentity.CognitoUserAttribute(dataEmail);
var attributePhoneNumber = new AmazonCognitoIdentity.CognitoUserAttribute(dataPhoneNumber);
var attributeName = new AmazonCognitoIdentity.CognitoUserAttribute(dataName);
var attributeFamilyName = new AmazonCognitoIdentity.CognitoUserAttribute(dataFamilyName);

attributeList.push(attributeEmail);
attributeList.push(attributePhoneNumber);
attributeList.push(attributeName);
attributeList.push(attributeFamilyName);
attributeList.push(attributeMiddleName);

var username=dataEmail.Value
var password='************'
userPool.signUp(username, password, attributeList, null, function(err, result){
    if (err) {
        console.log(err);
        return;
    }
    cognitoUser = result.user;
});
im1dermike commented 6 years ago

Thanks for your quick reply.

This appears to be the code that is already in your user-registration.service.ts file's register() function. I'm not sure how this pertains to the newPassword() function and/or how I should change the newPassword() function.

jafetmorales commented 6 years ago

Just change the code in your callback to this. Notice how am passing userAttributes:

        userAttributes.given_name='Jafet'
        cognitoUser.completeNewPasswordChallenge(newPassword, userAttributes, this);

If this gives you more variables missing, just keep adding them to userAttributes, until you get no error.

im1dermike commented 6 years ago

That was one of the first things I tried.

cognitoUser.authenticateUser(authenticationDetails, {
    newPasswordRequired: function (userAttributes, requiredAttributes) {
        // User was signed up by an admin and must provide new
        // password and required attributes, if any, to complete
        // authentication.

        // the api doesn't accept the email verified field back
        delete userAttributes.email_verified;
        userAttributes.given_name = newPasswordUser.givenName;
        userAttributes.family_name = newPasswordUser.familyName;
        console.log('userAttributes: ' + JSON.stringify(userAttributes));

        cognitoUser.completeNewPasswordChallenge(newPasswordUser.password, requiredAttributes, {
            onSuccess: function (result) {
                callback.cognitoCallback("", userAttributes);
            },
            onFailure: function (err) {
                callback.cognitoCallback(err, null);
            }
        });
    },
    onSuccess: function (result) {
        callback.cognitoCallback("", result);
    },
    onFailure: function (err) {
        callback.cognitoCallback(err, null);
    }
});

When I check the console log I added for userAttributes, I see:

userAttributes: {"given_name":"Test","family_name":"User","email":"my@email.com"}

Those values were empty strings before I added those lines. Nonetheless, I get the same error.

jafetmorales commented 6 years ago

But it seems like you are still passing empty attributes to the call that completes the challenge. Change this line: cognitoUser.completeNewPasswordChallenge(newPasswordUser.password, requiredAttributes, { To the following: cognitoUser.completeNewPasswordChallenge(newPasswordUser.password, userAttributes, {

im1dermike commented 6 years ago

I'm going to continue to test, but that appears to work.

The code that used requiredAttributes came from your code for what it's worth. https://github.com/awslabs/aws-cognito-angular2-quickstart/blob/master/src/app/service/user-registration.service.ts

jafetmorales commented 6 years ago

The original code which spits out the error is from AWS developers, not mine. You can use requiredAttributes or userAttributes, as long as you fill all required attributes. They just didn't want to fill your required attributes with dummy values and that's why they put the comment there so that we don't forget to fill them out ourselves.

vbudilov commented 6 years ago

Closing due to lack of activity (seems to be solved). Thanks @jafetmorales