user authentication check using sts token instead of user/pass - amazon-web-services

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.

Related

AWS Cognito Error: No Cognito Identity pool provided for unauthenticated access

var normalAuth = async (username, password) => {
try{
var user = await Auth.signIn(username, password)
console.log(user)
if(user.challengeName === "NEW_PASSWORD_REQUIRED"){
console.log("assigning new password!")
user = await Auth.completeNewPassword(user, "password") // give the user a new password. this would NOT be included in any kind of production code, its only here as a work around
console.log(user)
} // work around. users created in the console are only given temporary passwords, and as such have no authorization
// setting a new password will fix this
console.log(await Auth.currentCredentials()) // THIS THROWS AN ERROR?!?!
setAuthState(false) // auth is no longer in progress
}
catch(error){
console.error(error)
}
}
I'm trying to grab the tokens from my Amplify user after authenticating but I'm receiving the error
No Cognito Identity pool provided for unauthenticated access
This is pretty strange because I'm not using an identity pool at all. My baseline assumption was that I shouldn't need to provide an identity pool ID at all in my amplify config.
config looks like this
var amplifyConfig = {
Auth: {
mandatorySignIn: false,
region: "us-east-1",
userPoolId: "mypoolid",
userPoolWebClientId: "myclientid"
}
}
The really weird part is that the tokens are actually there in user after I authenticate. It's only when I try and retrieve them this way specifically that an error is thrown.
Any idea what's going on here?

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

User ID in Cognito

I use AWS API Gateway + AWS Cognito (Federated Identity + User Pool). I'm creating REST API in API Gateway. There are methods for getting users list and for getting user by id. What should I use as user ID?
Response should contain te following user data: ID, username, first name, last name etc. Username, first name, last name are stored in User Pool attributes.
I see in examples that they use cognitoIdentityId as User ID. If I will use cognitoIdentityId as ID, then how should I get user data by this ID? Please give me an example or link to API reference how to get user data by cognitoIdentityId.
You should be able to get user attributes as shown in the following example using the Username.
var AWS = require('aws-sdk');
AWS.config.region = 'us-east-1'; //This is required to derive the endpoint
var poolData = { UserPoolId : 'us-east-1_TcoKGbf7n',
ClientId : '4pe2usejqcdmhi0a25jp4b5sh3'
};
var userPool = new AWS.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
var userData = {
Username : 'username',
Pool : userPool
};
var cognitoUser = new AWS.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.getUserAttributes(function(err, result) {
if (err) {
alert(err);
return;
}
for (i = 0; i < result.length; i++) {
console.log('attribute ' + result[i].getName() + ' has value ' + result[i].getValue());
}
});
Reference: Examples: Using the JavaScript SDK
If you need to query the user attributes using AccessToken, then use the following example.
var params = {
AccessToken: 'STRING_VALUE' /* required */
};
cognitoidentityserviceprovider.getUser(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
Reference: AWS JavaScript SDK GetUser
Note: Currently there is no support in both AWS JavaScript SDK and API to get the user attributes by UserId.

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

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

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.