Allow CognitoUser to use AWS Lambda - amazon-web-services

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));

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

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
},
});

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 js: getCurrentUser() returns null

Building a simple application using the examples on their github page. I can log into my application using Cognito. What I can not do is logout because no matter what I try I can't get a hold of the user object. I've dorked around with various other calls to no avail (found here on their API page). The only other post on SO I found isn't applicable because I'm not using Federated Identity. The code I'm using is pretty much verbatim what's on the github page, but will post here for convenience:
login code:
var userName = $('#user_name_login').val();
var userPassword = $('#user_password_login').val();
var userData = {Username: userName, Pool : userPool};
var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
var authenticationData = {Username : userName, Password : userPassword};
var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
// now that we've gotten our identity credentials, we're going to check in with the federation so we can
// avail ourselves of other amazon services
//
// critical that you do this in this manner -- see https://github.com/aws/amazon-cognito-identity-js/issues/162
// for details
var loginProvider = {};
loginProvider[cognitoCredentialKey] = result.getIdToken().getJwtToken();
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: identityPoolId,
Logins: loginProvider,
});
// //AWS.config.credentials = AWSCognito.config.credentials;
// AWSCognito.config.credentials = AWS.config.credentials;
// //call refresh method in order to authenticate user and get new temp credentials
// AWS.config.credentials.refresh((error) => {
// if (error) {
// alert(error);
// } else {
// console.log('Successfully logged in!');
// }
// });
// this is the landing page once a user completes the authentication process. we're getting a
// temporary URL that is associated with the credentials we've created so we can access the
// restricted area of the s3 bucket (where the website is, bruah).
var s3 = new AWS.S3();
var params = {Bucket: '********.com', Key: 'restricted/pages/user_logged_in_test.html'};
s3.getSignedUrl('getObject', params, function (err, url) {
if (err) {
alert(err);
console.log(err);
}
else {
console.log("The URL is", url);
window.location = url;
}
});
},
mfaRequired: function(session){
new MFAConfirmation(cognitoUser, 'login');
},
onFailure: function(err) {
alert("err: " + err);
},
});
I'm attempting to logout by executing:
userPool.getCurrentUser().signOut();
Note that the userPool and such are defined in another file, and is initialized thusly:
var poolData = {
UserPoolId : '*****',
ClientId : '*****'
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
so how do I sign my users out of the application?
closing this as the issue, as stated here, turned out to be a red herring. if you're doing what I was trying to do above in using cognito to generated a signed url to access an html file located in a restricted 'folder' in the bucket and you want to be able to logout from that new window location, make sure the signed url is of the same domain as your landing page.
for example, if you land at foo.com because you've got an A or CNAME DNS record set up so that your users don't have to hit a doofy cloudfront or s3 generated url in order to get to your website, you need to make sure you ALSO generate a signed URL that has the same domain name. Otherwise you won't be able to access the bucket. Moreover - you won't be able to access your user object because the session object is keyed to a different domain name than the one you're currently at.
see this for information on how to specify what the domain of the signed url should be.
and also note that there's a lot of trouble you can get into if you are using a third-party domain registar. I just burned two weeks unborking myself because of that :-/

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.