Getting - UserNotFoundException - while calling adminCreateUser - AWS Cognito - amazon-web-services

I am having a very peculiar issue regarding User creation in AWS Cognito.
When I am in the same region (e.g US-East-AWS and Creating User from NA) then it is working like a charm. But when someone is in other region (e.g US-EAST-AWS and creating user from EU with a slow internet connection) then I am getting UserNotFoundException.
Below is the how I am handling User creation in my Lambda function (JS)
await cognitoidentityserviceprovider.adminCreateUser(params).promise()
if (customer.MFA === true) {
await toggleCognitoUsersMFA(jsonBody.email, true)
}

Check your MessageAction value in your params.
If the value is set to RESEND, and you're creating a new user, you'll get this User Not Found message.
The current AWS docs indicate that either a RESEND or SUPPRESS value is required, this is not true, you can actually omit the value.

Related

AWS SES: Can't send emails from any one of the new regions

I have the problem that i can't send emails from the new aws ses environments, which were introduced a month ago.
All the old ones are working fine (e.g. us-east-1, us-west-2, eu-west-1).
But if I want to send a mail from one of the new environments, e.g. eu-central-1, I just get the error message:
The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
But this can't be the case, because all the old ones are working fine with the same keys.
Therefore I would really appreciate it if sb else could test the sample code with their account to check if they have the same issue.
The new environments are eu-central-1, ap-south-1 and ap-southeast-2. Endpoint Urls
Sample Code:
var ses = require('node-ses');
var client = ses.createClient({ key: '', secret: '', amazon: 'https://email.eu-central-1.amazonaws.com'});
async function sendMessage() {
let options = {};
options.from = "test#aol.com";
options.to = "test2#aol.com";
options.subject = "TestMail";
options.message = "Test";
console.log("Try to sendMessage");
client.sendEmail(options, function (err, data, res) {
console.log("Error: " + JSON.stringify(err));
console.log("Data: " + data);
console.log("res: " + res);
});
}
sendMessage();
The sample code uses the node-ses npm package and you just need to enter aws iam user credentials, which have ses access.
If you want to check different regions, you have to change url in the createClient constructor.
Dont worry, the sample code does not send an email!!!
If the region is working, it should throw an error message similar to this: Email address is not verified. The following identities failed the check in region EU-WEST-1: test#aol.com, test2#aol.com"
Otherwise the error will be the one described above.
I also have to mention that I am currently still in sandbox mode, so maybe the new regions are blocked for sandbox users?
It's because you must be creating the SES credentials from the IAM console . You should instead create the credentials using the SES interface/console.
Follow this article to create smtp credentials using SES interface:
http://docs.amazonwebservices.com/ses/latest/GettingStartedGuide/GetAccessIDs.html.

send email when user registers - AWS Cognito federated Identities

How can i send an email/trigger a lambda function when a new user registers?
Under "edit identity pool" i only found a sync trigger.
If i understand correctly: This one is triggered every time a user syncs his data...
Is there any way to trigger a lambda function only for the "initial" sync or when a certain dataset is created for the user?
Edit:
To be more specific: I do create the user via lambdas using the JS SDK. I use developer authentication with my own oauth2 flow. I don't know how to distinguish between a user granting access e.g. via Google the first time from someone doing this the second time. The json with the access code seams the same to me... Maybe I am mistaken.
Also using the getOpenIdTokenForDeveloperIdentity call I don't know how to distinguish between an ID that is new to cognito from one cognito already knows.
Edit 2:
To be even more precise:
I am building on this project: https://github.com/laardee/serverless-authentication-boilerplate/blob/master/authentication/lib/storage/usersStorage.js
here is how i do save the User to cognito at the moment.
I do run this code for first time users as well as nth time users. My problem is that i dont know how to distinguish...
const saveCognito = (profile) => new Promise((resolve, reject) => {
if (profile) {
cognitoidentity.getOpenIdTokenForDeveloperIdentity({
IdentityPoolId: process.env.COGNITO_IDENTITY_POOL_ID,
Logins: {
// profile.userId = encrypted id of the e.g. google oauth2 id
[process.env.COGNITO_PROVIDER_NAME]: profile.userId
}
}, (err, dat) => {
if (err) {
reject(err);
} else {
var list_params = {
DatasetName: 'user-data', /* dataset name */
IdentityId: dat.IdentityId, /* cognito id */
IdentityPoolId: process.env.COGNITO_IDENTITY_POOL_ID
};
cognitosync.listRecords(list_params, function(err, data) {
if (err) {
reject(err); // an error occurred
} else {
var RecordPatches = //[Parts of the i want to write to the user]
// SyncSessionToken is returned by the cognitosync.listRecords call
list_params["SyncSessionToken"] = data.SyncSessionToken;
list_params["RecordPatches"] = RecordPatches;
cognitosync.updateRecords(list_params, function(err, update_data) {
if (err){
reject(err);
} else {
resolve();
}
});
}
});
}
});
} else {
reject('Invalid profile');
}
});
So this is something which is not currently supported in Cognito out of the box. You are correct in saying that the only built in Cognito Event that will trigger a Lambda Function is the "Sync Trigger" Event. This Sync event is fired every time that a Cognito IdentityId Synchronizes some of their data to the Cognito Sync cloud data store.
This event is unrelated to the creation of a new IdentityId by Cognito Federated Identity.
You could in theory:
Run a list-identities call on the IdentityPool, before the user logs
in.
Login the user. Check whether the IdentityId which has been given to the user is present in the list you retrieved before they logged
in. This would tell you whether or not the identity that they were
given existed before this login.
Based on this information you could
make a decision whether or not to programatically call the Lambda
Function from your application.
The setup of the above would be complex, as for security reasons you would need to maintain this service, server-side. The list-identities call requires AWS credentials to call. And I doubt you'd want to include permissions for that call in your IAM policy for unauthenticated users.
Aside from the above there is not much you can do at the moment.
In order to do this, you would need to setup a DynamoDB table (or some similar low latency datastore) where you could maintain the state of the IdentityId list, and then query this service/store whenever you login a user to compare new logins to the pre-existing list.
If this is critical to your use case I would suggest heading over to AWS Support, and create a case where you can log this as a feature request.
https://aws.amazon.com/premiumsupport/

AWS: How to check that credentials are correct?

The following function (in Javascript) is supposed to accept accessKey and secretKey and check whether they are correct:
function checkKeys(accessKey, secretKey) {
var cred = new AWS.Credentials(accessKey, secretKey, null);
cred.get(function(err) {
if (err) {
console.log("ERROR!")
} else {
console.log("Keys are OK")
}
})
}
I'd expect that get() method returns an error in case of incorrect credentials. I don't know why, but it doesn't matter what credentials I give, I never get an error, and console always prints "Keys are OK".
You cannot really check that credentials are "correct". Think about user roles. User may be authorized to make one API call, but not another. The only generic thing you can do is make sure that ID+key pair you have are valid AWS credentials with STS.getCallerIdentity() (see SDK docs for details). Note that it will return caller details even if this caller has no access to any of the services, so take the results with a grain of salt.
You're just storing credentials in a local object, and then retrieving them. You need to trigger an actual AWS API call in order to verify if the credentials are valid.

AWS Lambda error on Cognito User Pool trigger

I'm trying to insert a record into DynamoDB invoking "Pre sign-up" trigger of Cognito User Pool.
Lambda function is pretty simple for testing purposes but there is always an error in client application on AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool.signUp call
Use case 1
Lambda body:
console.log('Received event:', JSON.stringify(event, null, 2));
Result:
InvalidLambdaResponseException: Invalid lambda function output : Invalid JSON
Use case 2
Lambda body:
callback("null", "success");
Result:
InvalidLambdaResponseException: Invalid lambda function output : Invalid JSON
Use case 3
Lambda body:
new AWS.DynamoDB.DocumentClient().put(params, callback);
Result:
InvalidLambdaResponseException: Invalid cognito sign in version. Version should be 1
So, any ideas what might be wrong?
Could the latest error might be related to the beta status of Cognito User Pool?
P.S. I will provide more details if needed. Thanks in advance.
You are doing this in node.js and the error indicates you are not returning the service expected event source.
You should call context.done() when your lambda function finishes execution. Also, in any of the trigger sources which Cognito User Pool service generates, you can only edit the "response" part of the the source. For example, "autoConfirmUser" flag in PreSignUp trigger source.
Look at the examples in our developer guide for more details on this.
#user3479125
To do the same in python just return an event as is, or with modifications in datasets.
This code is supposed to run between the mobile device and cognito, so it can modify the event and it should return it back, so Sync event will finish successfully.
Some more explanations here
Try returning callback("null", event);
This should solve your problem.

How to check if email is valid before send through Amazon SES

I am fresh in implementing Amazon Web services. I am working on implementing an application for sending bulk emails from a queue. I have to check emails and remove non-verified emails from the queue before sending.
My question is: Is there any method available in Amazon to check whether emails are valid or not?
From your question, it is not clear whether you want to:
1-avoid sending messages to malformed email addresses; or
2-avoid sending messages to email addresses which are not verified under your AWS account.
The answer for 1 is spread in different forms accross forums, SO, etc. You either do it simple, i.e., craft a short and clear regular expression which validates roughly 80% of the cases, or you use a very complex regular expression (in order to validate against the full compliance -- good luck, check this example), check whether the domain is not only valid but also up and running, and, last but not least, check if the account is valid under that domain. Up to you. I'd go with a simple regex.
The answer for 2 is available at Verifying Email Addresses in Amazon SES -- the Amazon SES API and SDKs support the operations below, so you should be covered in any case:
Using the Amazon SES API
You can also manage verified email addresses with the Amazon SES API. The following actions are available:
VerifyEmailIdentity
ListIdentities
DeleteIdentity
GetIdentityVerificationAttributes
Note
The API actions above are preferable to the following older API actions, which are deprecated as of the May 15, 2012 release of Domain Verification.
VerifyEmailAddress
ListVerifiedEmailAddresses
DeleteVerifiedEmailAddress
You can use these API actions to write a customized front-end application for email address verification. For a complete description of the API actions related to email verification, go to the Amazon Simple Email Service API Reference.
You can use the "getIdentityVerificationAttributes" operation to check whether emails are valid or not. You can use this as shown below:
var params = {
Identities: arr // It is a required field (array of strings).
};
ses.getIdentityVerificationAttributes(params, function(err, data) {
if(err)
console.log(err, err.stack); // an error occurred
else
console.log(data); // successful response
});
And the Response will be:
{ ResponseMetadata: { RequestId: '7debf2356-ddf94-1dsfe5-bdfeb-efsdfb5b653' },
VerificationAttributes:
{ 'abc#gmail.com': { VerificationStatus: 'Pending' },
'xyz#gmail.com': { VerificationStatus: 'Success' } } }
If there is an email-id which is not sent previously for email verification request, then there is no key present in 'VerificationAttributes' object.
AmazonSimpleEmailServiceClient ses= new AmazonSimpleEmailServiceClient(credentials);
List lids = ses.listIdentities().getIdentities();
if (lids.contains(address)) {
//the address is verified so
return true;
}