AWS Cognito - Custom email message with Lambda trigger being overwritten - amazon-web-services

I'm using a lambda function to customize confirmation emails with AWS Cognito. My lambda function seems to work fine and looks like this:
exports.handler = async (event, context, callback) => {
const sampleTemplate = `<html>
<body>
<div>${event.request.codeParameter}</div>
<div>${event.userName}</div>
</body>
</html>`
if (event.triggerSource === "CustomMessage_AdminCreateUser") {
event.response.emailSubject = 'Lets hope this works'
event.response.emailMessage = sampleTemplate
console.log(event.response) // Logs look as expected
}
callback(null, event);
};
The problem is that when the emails arrive the message body is being overwritten by the content in the User Pools > Message Customizations tab. The subject line is working fine, but the email body is being overwritten. For example, the cognito settings look like this:
And the emails look like this:
As you can see, the lambda function worked for setting the email's subject line, but not the actual content. I can't find any setting to turn off that content and it can't be left blank... Any help is much appreciated.

For anyone finding this, I was able to find the answer. When using the CustomMessage_AdminCreateUser event, cognito will silently throw an error if you use event.userName in the template. Instead use event.request.usernameParameter and it will work

If after doing everything, your custom email template doesn't show up then check the following:
Verification type is set to "code" not "link". ( Your Pool > General settings > message customizations ) Ref: https://github.com/amazon-archives/amazon-cognito-identity-js/issues/521#issuecomment-358383440
Email HTML template shouldn't exceed more than 20,000 UTF characters. Ref: https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-custom-message.html#aws-lambda-triggers-custom-message-example
Check this tutorial - https://medium.com/#hasnat_33856/customize-your-cognito-verification-emails-with-html-pages-using-lambda-function-e6fff7ebfb94

We MUST include both the "{username}" and "{####}" placeholder for the custom template for CustomMessage_AdminCreateUser to work. We can place this ourselves in the html file or via the event object's values for the keys event.request.usernameParameter and event.request.codeParameter respectively.
In summary, the html file for CustomMessage_AdminCreateUser must include these two values:
event.request.usernameParameter (has value "{username}") and
event.request.codeParameter (has value "{####}")

Related

Customize email verification page AWS Cognito

I am using Amazon Cognito for user authentication. After the user is registered verification email is sent to his email address. After clicking on the email link he is prompted with this in his browser.
How can I customize this page in order to insert a script that will trigger deep links within the mobile application, and also make the page look bit nicer?
You can do that using Cognito triggers.
You can configure a trigger template to define a message with a link to a page you control.
The assets will be stored at: amplify/backend/auth/<your-resource-name>CustomMessage/assets
The documentation has more details
Cognito allows you to configure your User Pool to send an email to
your users when they attempt to register an account. You can configure
this email to contain a link to Cognito’s Hosted UI where the user’s
account will be marked as confirmed.
This trigger template allows you to define an email message with a
link to a static S3 bucket that you control, where the user’s account
will be confirmed and they can then be redirected to a URL of your
choice (presumably your application). The URL will automatically
contain the username as a query string parameters.
Please note that this trigger template will create an S3 resource. The
files that populate the static site are available for edit in
amplify/backend/auth/CustomMessage/assets. They
consist of:
index.html
spinner.js (controls the spinner that appears on the page while users are awaiting confirmation)
style.css
verify.js (the script which performs the verification request)
I was not able to customize the verification page provided by AWS. I created my own UI on my page, which sent the generated code to cognito for verification. For that I needed to:
trigger custom email upon registration
put custom link to verification in the email using the codes provided for the lambda
process the codes on my page
send the codes and username through aws package
Step 1.
In AWS Cognito User Pool, customize workflow with triggers, choose "Custom Message". The triggerSource for verification that I check for are:
event.triggerSource === 'CustomMessage_SignUp' || event.triggerSource === 'CustomMessage_ResendCode'
You can see other trigger sources for CustomMessage here: https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-custom-message.html
Step 2. The lambda provides parameters for verification for my users: event.request.userAttributes.sub and event.request.codeParameter. Using these to I constructed a link to my page like so:
https://mypage.com?user_name=${event.request.userAttributes.sub}&confirmation_code=${event.request.codeParameter}
Step 3. On my page, I check if the url params for user_name and confirmation_code are present, and display a modal which is supposed to inform the user if the verification went correctly or not.
Using a package "amazon-cognito-identity-js" I process the code and user_name. First I create the user pool:
import { CognitoUserPool } from 'amazon-cognito-identity-js';
//Aws-cognito credentials
const poolData = {
UserPoolId: YOUR_USERPOOL_ID,
ClientId: YOUR_CLIENT_ID,
};
export default new CognitoUserPool(poolData);
Then to process the code I create a user instance:
import { CognitoUser } from 'amazon-cognito-identity-js';
import UserPool from 'utils/UserPool';
const getUser = () => {
return new CognitoUser({
Username: user_name.toLowerCase(),
Pool: UserPool,
});
};
// After that you can process the code:
getUser().confirmRegistration(code, false, function (err, result) {
if (err) {
if (
err.message === 'User cannot be confirmed. Current status is CONFIRMED'
) {
// Handle already confirmed error
} else {
// Handle other errors you want
}
}
// Handle successful verification
});
The account is verified and you can guide the user to the login page or any other.

Cognito Custom Message Trigger doesn't have any effect

I am trying to customize the message sent to the user pre-verification by using the custom message trigger, I verified that the data returned from the lambda is valid and the modifications are as I want them to be, however it seems that those changes are not taking any effect as I get the standard verification details to my email
I failed to find any solutions in aws docs, anyone had the same issue ?
package main
import (
"fmt"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
// Handler will handle our request comming from the API gateway
func Handler(event events.CognitoEventUserPoolsCustomMessage) (events.CognitoEventUserPoolsCustomMessage, error) {
if event.TriggerSource == "CustomMessage_SignUp" {
event.Response.EmailMessage = "Welcome to myapp, please click the following link to verify your email, this is a custom message"
event.Response.EmailMessage = fmt.Sprintf(`Please click the link below to verify your email address. https://apigateway.myapp.com/auth/validate?client_id=%s&user_name=%s&confirmation_code=%s`, event.CallerContext.ClientID, event.UserName, event.Request.CodeParameter)
}
return event, nil
}
func main() {
lambda.Start(Handler)
}
It seems that in the cognito panel under message customizations verification type code needs to be checked (not link), after I did that the trigger does change the message
It works also for verification link, but you have to use the code parameter as {##Verify email##} and not {####} in your User Pool - Message customization settings. And then also use {##Verify email##} keyword in your html template.

How to reject sign-up trigger with GoLang

I've successfully created a lambda function using Go for the pre sign-up trigger of AWS Cognito.
My problem is that I'm not being able to deny/reject the user if a custom field is not valid (based on custom logic).
I'm returning an error as described in AWS Cognito trigger's guide:
return event, fmt.Errorf("Invalid value for field 'custom:myField'")
also I've tried this options:
returning an empty event (nil is not allowed for the event):
var emptyEvent events.CognitoEventUserPoolsPreSignup
return emptyEvent, fmt.Errorf("Invalid value for field 'custom:myField'")
changing ValidationData in the original event:
event.Request.ValidationData = map[string]string{"custom:myField": "Invalid value for field 'custom:myField."}
return event, fmt.Errorf("Invalid value for field 'custom:myField'")
changing UserAttributes in the original event
event.Request.UserAttributes["email"] = ""
return event, fmt.Errorf("Invalid value for field 'custom:myField'")
All those methods are failing, the user is always created in the User Pool.
What should be the correct way to reject the sign-up request using GoLang lambda function?
Looks like something changed on AWS Cognito Lambda triggers, since today I tried the following source code and it worked as expected:
func handler(event events.CognitoEventUserPoolsPreSignup) (events.CognitoEventUserPoolsPreSignup, error) {
fmt.Println(event)
return event, fmt.Errorf("TESTING LAMBDA ERRORS WITH GOLANG")
}
Also, the previous source code that was not working as expected when I posted this question is currently working (with no changes on my side).

Configure a Custom SMS Message for MFA in AWS Cognito

I Am using AWS Cognito for authentication in a web application.
If a user Forgets their password I have a Lambda Function Trigger that sends a custom email with a link that has the users email address and the verification code in so they can click the link and just enter their new password.
So There is a new requirement that should allow the user to receive an sms, but currently it looks like if you enable MFA for sending the SMS, you can only customise the message in the console area and in the Lambda function,
this event.response.smsMessage does not seem to do anything.
So if the user has phone_number_verified true, it sends the sms without triggering the Lambda function.
exports.handler = function(event, context) {
if(event.triggerSource === "CustomMessage_ForgotPassword") {
var url = 'http://myurl.com/forgotpassword/'+ event.request.userAttributes.email+'/'+event.request.codeParameter
event.response.smsMessage = 'Password Reset: Click the link ' + url + ' or enter Verification Code: ' + event.request.codeParameter
event.response.emailSubject = " Password reset";
event.response.emailMessage = "Custom HTML goes here";
}
context.done(null, event);
};
This is currently the Lambda function configure on custom message trigger in the cognito User pool.
After a long discussion with AWS support, They came to the resolution that my SMS text was more than 140 chars. Yes 140, And then the SMS would not be sent rather the email would. No errors in logs or anything whatsoever.
So they said they will look into adding something in the logs that at least tells you that the SMS was not sent because the character limit was exceeded.

How to use custom mailgun variable inside email template?

I'm using mailgun-js library to send emails from nodejs server.
How I can populate html email teamplate, which sends through mailgun, with some custom variable?
For recipient-variables it works like %recipient.custom-variable% in html template and with such code on server side:
let email = {
from: 'my#email.com',
to: emailsArray,
subject: 'my subject',
html: template,
'recipient-variables': emailsArray.map(e=>{e:{custom-variable: user.customThing}})
};
return mailgun.create(email);
but I have some variable which should be the same for all recipients.
How I can set the custom variable and how I can use it inside template (in manner of recipient-variable)?
It seems like it's not possible to use custom variables, only with recipient-variables.