amazon-cognito-identity-js - Trouble Authenticating a User via email - amazon-web-services

If I follow the example "Authenticate a User" shown on the http://docs.aws.amazon.com/cognito/latest/developerguide/using-amazon-cognito-user-identity-pools-javascript-examples.html page or the "Use case 4" example on the https://github.com/aws/amazon-cognito-identity-js/blob/master/README.md page using the Username, the example works.
I am trying to authenticate a user using their email attribute, rather than their username. I have marked the email attribute as an Alias in my User Pool.
User Pools Console in AWS
When I use email in place of username in the "Authenticate a User" example I get the following error: ResourceNotFoundException: Username/client id combination not found. I have included my code sample below.
How does one Authenticate a User via email address using the "Amazon Cognito Identity SDK for JavaScript" (https://github.com/aws/amazon-cognito-identity-js)?
Code Sample
function authenticateUserViaEmail() {
log("authenticateUserViaEmail called");
// Initialize the Amazon Cognito credentials provider
AWS.config.region = 'us-east-1'; // Region
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: identityPoolId,
});
AWSCognito.config.region = 'us-east-1';
AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: identityPoolId,
});
var authenticationData = {
Username : document.getElementById("email").value,
Password : document.getElementById("password").value
};
log("using: " + JSON.stringify(authenticationData));
var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
var poolData = { UserPoolId : userPoolId,
ClientId : clientId
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
var userData = {
Username : document.getElementById("email").value,
Pool : userPool
};
var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
log("About to call authenticateUser...");
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
log('Access token: ' + result.getAccessToken().getJwtToken());
},
onFailure: function(err) {
log(err);
console.error(err);
},
});
}

Did you confirm your email address? If you did not confirm your email address, it cannot be used as an alias for logging in.

Related

Cannot fetch the authentity token from AWS

I want to fetch the authentication tokens from AWS;
however, I only receive an error telling me
that the client id is not correct.
I was very happy to have found this code on the web,
link: https://docs.aws.amazon.com/cognito/latest/developerguide/authentication.html
and I was able to invoke the last function call,
but it complains about the ClientId, and I have no clue
where to fetch the Clientid from :-(
I am not sure from where to fetch the Client Id and User Pool Id from?
There is also a Client App Id on the AWS web site.
I am looking for something where I only have to provide
the userid and password using node js?
const AmazonCognitoIdentity = require('amazon-cognito-identity-js');
var authenticationData = {
Username : '...',
Password : '...',
};
var authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(authenticationData);
var poolData = {
UserPoolId : '...', // From where on the AWS web site can I fetch the correct User Pool Id?
ClientId : '...' // From where on the AWS web site can I fetch the correct client Id?
};
var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
var userData = {
Username : 'karlschmitt',
Pool : userPool
};
var cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
var accessToken = result.getAccessToken().getJwtToken();
/* Use the idToken for Logins Map when Federating User
Pools with identity pools or when passing through an
Authorization Header to an API Gateway Authorizer */
var idToken = result.idToken.jwtToken;
console. log("Successful!");
},
onFailure: function(err) {
// alert(err);
console. log("Failure!" + err.message);
},
});
Create Congnito User Pool - Here is a link and grab Pool Id from General Settings
Register your application as a Client - Here is a link and grab client id

Allow CognitoUser to use AWS Lambda

My problem:
Using AWS SDK to invoke an AWS Lambda is giving me config errors
CredentialsError: Missing credentials in config
What I found:
Loggin in a user for the first time initiates proper config settings, but it's lost upon page refresh.
The Goal:
Use...the code below, even after the user has refreshed the page
lambda.invoke(params, function(err, data) {
if (err) {
// console.log(err, err.stack);
} else {
console.log(data);
} // successful response
});
Below is how I signIn a user from a cognitoUserPool the 1st time
Step 1 capture username and password
trySignIn(username, password) {
console.log("trying to sign in");
var authenticationData = {
Username: username,
Password: password
};
Step 2 use new AmazonCognitoIdentity.AuthenticationDetails
var authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(
authenticationData
);
Step 3 configure UserPool with UserData
var poolData = {
UserPoolId: "myPoolId", // Your user pool id here
ClientId: "myPoolClient" // Your client id here
};
var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
var userData = {
Username: username,
Pool: userPool
};
Step 4 Get a CognitoUser object
var cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function(result) {
var accessToken = result.getAccessToken().getJwtToken();
console.log(result);
//POTENTIAL: Region needs to be set if not already set previously elsewhere.
//AWS.config.region = "us-east-1"; //moved to component did mount
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: "myidentiy-id-pool-id", // your identity pool id here
Logins: {
// Change the key below according to the specific region your user pool is in.
"cognito-idp.us-east-1.amazonaws.com/us-east-1": result
.getIdToken()
.getJwtToken()
}
});
Step 5 Here we can configure the AWS SDK to use things like AWS.Lambda / AWS.S3
//refreshes credentials using AWS.CognitoIdentity.getCredentialsForIdentity()
AWS.config.credentials.refresh(error => {
if (error) {
console.error(error);
} else {
// Instantiate aws sdk service objects now that the credentials have been updated.
// example: var s3 = new AWS.S3();
console.log("Successfully logged!");
}
});
Problem is event after saving the UserObject to storage I lose the AWS.config information and I can't reconfigure it without asking for the users password everytime
var user = { username: username };
localStorage.setItem("cognitoUser", JSON.stringify(user));
console.log(cognitoUser);
console.log(user);
The Question ?
How can I configure AWS.config having only access to the cognitoUser Object from storage, but not the user password
Update: <-- Did Not Work
I'm thinking it might be possible to save the variable created in Step 5 to storage.
var lambdaTry = new AWS.Lambda
localStorage.setItem("lambdaTry", JSON.stringify(lambdaTry));

Using instagram as an 'authorizer' for API Gateway - AWS Cognito

I am using Congnito User Pool to perform API Gateway authorization which is working fine. Now, I am trying to add Instagram as one of the login provider, for that I created Custom Authentication Provider in Federated Identities and using code below:
var cognitoidentity = new AWS.CognitoIdentity({ apiVersion: '2014-06-30' });
var params = {
IdentityPoolId: 'us-east-1:7d99e750-.....',
Logins: {
'login.instagram': 'Access-Token-Returned-By-Instagram',
},
TokenDuration: 60
};
cognitoidentity.getOpenIdTokenForDeveloperIdentity(params, function (err, data) {
if (err) {
console.log(err, err.stack);
} else {
console.log(data);
var idParams = {
IdentityId: data['IdentityId'],
Logins: {
'cognito-identity.amazonaws.com': data['Token']
}
};
cognitoidentity.getCredentialsForIdentity(idParams, function (err2, data2) {
if (err2) console.log(err2, err2.stack); // an error occurred
else console.log(data2); // successful response
});
}
});
I am able to get accessToken and sessionToken, however, I am still unable to find a way to get idToken and accessToken which is required by API Gateway to authorize the incoming request.
I tried looking into SDK as well as AWS forum, but I am still unable to find a way to use custom federated identity provider to authorize API Gateway which use a cognito user pool.
I am going to take a whirl at this....
Do you have a cognito user?
No
import { CognitoUser, CognitoUserPool, AuthenticationDetails } from "amazon-cognito-identity-js";
let cognitoUser;
const userPool = new CognitoUserPool({
UserPoolId: config.USER_POOL.pool_Id, //your userpool id
ClientId: config.appClientId, //your appClient
});
const userData = {
Username: 'user name',
Pool: userPool
};
cognitoUser = new CognitoUser(userData);
/* Should now have a cognitoUser */
Authenticate your cognito user
const authenticationData = {
Username : payload.userName,
Password : payload.password,
};
const authenticationDetails = new AuthenticationDetails(authenticationData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
const accessToken = result.getAccessToken().getJwtToken();
/* Use the idToken for Logins Map when Federating User Pools with identity pools or when passing through an Authorization Header to an API Gateway Authorizer*/
const idToken = result.idToken.jwtToken;
/*
Do something with
idToken
accessToken
I would write them to a file or encrypt them and store them on the localStorage OR encrypt and save in REDUX store.
*/
},
onFailure: function(err) {
//handle error
},
});

AWS cognito forgot password flow

I've created an AWS cognito user pool with email as required attribute and checked email for verification. The users are created from my java spring backend service using AWSCognitoClient sdk and calling adminCreateUser(createUser) method. The user gets an email with temporary password, which on signing in for the first time will set new password. Now when I execute the forgot password flow, I get the following error,
InvalidParameterException: Cannot reset password for the user as there is no registered/verified email or phone_number
Although I have received a temporary password to the email id I signed up for and changed my password for very first time I get the above error. Can someone explain what am I missing?
Below is the javascript code am executing for forgot password flow,
forgotPassword(username: String, poolInfo:any){
var poolData = {
UserPoolId : poolInfo.poolId, // Your user pool id here
ClientId : poolInfo.portalClientId // Your client id here
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
var userData = {
Username : username,
Pool : userPool
};
var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.forgotPassword({
onSuccess: function (result) {
this.router.navigate(['login']);
},
onFailure: function(err) {
alert(err);
},
//Optional automatic callback
inputVerificationCode: function(data) {
var verificationCode = prompt('Please input verification code ' ,'');
var newPassword = prompt('Enter new password ' ,'');
cognitoUser.confirmPassword(verificationCode, newPassword, this);
}
});
}
Resolved. I had to add "email_verified":"True" as an attribute for the users I created from my backend service.
I solved this issue with python:
response = cognito_client.get_user_attribute_verification_code(AccessToken='eyJraWQiOiJtTEM4Vm......',AttributeName='email')
response = cognito_client.verify_user_attribute( AccessToken='eyJraWQiOiJtTEM......', AttributeName='email', Code='230433')
def forgot_password(usename):
ClientId = 'f2va............'
response = cognito_client.forgot_password( ClientId=ClientId, Username=username)
def confirm_forgot_password():
ClientId = 'f2va............'
response = cognito_client.confirm_forgot_password(ClientId=ClientId,Username=username,ConfirmationCode='644603',Password='12345678')
Here is the Official Documentation.
https://boto3.amazonaws.com/v1/documentation/api/1.9.42/reference/services/cognito-idp.html#CognitoIdentityProvider.Client.confirm_forgot_password

user authentication check using sts token instead of user/pass

I am new to aws cognito. Here is what I am trying to do:
I have some users and I want them to login to my website and then as far as their session is valid I would like to keep them in without forcing them to sign in. So as far as I understand I need to generate STS token using cognito and send to the user and then in the next calls user will send the sts token as a header and I check the sts token using cognito and if it is valid I will serve the users.
For that I use the instruction in the following link:
https://github.com/aws/amazon-cognito-identity-js/
So specifically I use this part to authenticate the user and establish session:
var authenticationData = {
Username : 'username',
Password : 'password',
};
var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
var poolData = {
UserPoolId : '...', // Your user pool id here
ClientId : '...' // Your client id here
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
var userData = {
Username : 'username',
Pool : userPool
};
var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
console.log('access token + ' + result.getAccessToken().getJwtToken());
//POTENTIAL: Region needs to be set if not already set previously elsewhere.
AWS.config.region = '<region>';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId : '...', // your identity pool id here
Logins : {
// Change the key below according to the specific region your user pool is in.
'cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>' : result.getIdToken().getJwtToken()
}
});
// Instantiate aws sdk service objects now that the credentials have been updated.
// example: var s3 = new AWS.S3();
},
onFailure: function(err) {
alert(err);
},
});
So far so good. However, now in any subsequent call I do not want to sent
var authenticationData = {
Username : 'username',
Password : 'password',
};
and instead I want to use the sts token to authenticate the user:
var authenticationData = {
sts: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
};
var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
I do not see any example or usage of such a case. Is cognito the right service for this scenario and if yes how can I do the authentication check with sts?
I see that you are using AWS.CognitoIdentityCredentials in your authentication callback. That's used if your app needs AWS credentials to access various AWS services.
If your users are only interacting with your own website, the session you get after successful user authentication is valid up to 30 days by default.
You can check if the session is active or not by calling getSession on CognitoUser
https://github.com/aws/amazon-cognito-identity-js/blob/9e949c08188f13b8087106564e7b596ec58117ab/src/CognitoUser.js#L826
You can configure that duration by changing Refresh Token Validity for your client in Cognito User Pool console.