DEV Community

Cover image for Message Customization on Cognito
Jones Zachariah Noel for AWS Community ASEAN

Posted on • Updated on

Message Customization on Cognito

AWS Cognito has become one of the most adapted ways to authenticate your Modern applications (Click here to know more). The emails and SMS messages involved in the process of different actions, the modern applications need their own verbiage and also they have to be customization for each action.
Eg. For sign-up the application would have to send an email like -

Thank you for signing up. You can login with the <link>, you can download the app from the <link>.
Enter fullscreen mode Exit fullscreen mode

For forgot password, the application would have to send an OTP or link for resetting the password.

And many more use cases where the message would have to be customized in various way.

Ways to configure message customization

  • AWS Console
  • AWS CLI
  • Custom message via Lambda function trigger

AWS Console

In AWS Console, when can navigate to AWS Cognito User Pool and select the user pool you want to edit and navigate to the "Message Customization" tab.
SES Configuration
AWS gives the liberty of changing the sender email from the default "no-reply@verificationemail.com" to your own SES verified email identity, of-course this email identity has to be moved out of Sandbox environment. The selected email identity has to provide Cognito access to send emails, the respective IAM policy is required which is auto-created when you do from the web console.

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "stmnt1234567891234",
            "Effect": "Allow",
            "Principal": {
                "Service": "cognito-idp.amazonaws.com"
            },
            "Action": [
                "ses:SendEmail",
                "ses:SendRawEmail"
            ],
            "Resource": "<your SES identity ARN>"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

Once the permission is setup, you can customize the message which has to be delivered to the user. You can customize both email and SMS body. Email body is supported with HTML tags to format and beautify the email body.
Message customization
Cognito provides placeholders for username, password, code, link which are used to fill in the user specific values.

AWS CLI

AWS CLI makes it easier for terminal fond developers where the complete configuration is done with a single command. With the terminal/CLI you would have to specify the details as a JSON parameters. CLI provides a update-user-pool command for cognito-idp which could be used to update the custom messages.

aws cognito-idp update-user-pool 
--user-pool-id us-east-1_xxxxxxxxx 
--email-verification-subject "Your temporary password" 
--email-verification-message "<p>Your username is {username} and temporary password is {####}. </p>"
--email-configuration SourceArn=<YourSESIdentityARN>,ReplyToEmailAddress=<VerifiedSESIdentity>,EmailSendingAccount="DEVELOPER",From=<VerifiedSESIdentity>
Enter fullscreen mode Exit fullscreen mode

Custom message via Lambda function trigger

Lambda function could be added as a trigger to handle all custom message which gives you the total liberty to customize each and every message both email and SMS that is sent to the user.
Custom message trigger
Select your Lambda function and save the setting. This setting will trigger the selected Lambda function every time when Cognito is trying to send a message to the user.

Different event triggers which gets invoked -

  • CustomMessage_SignUp - When a new user signs-up and Cognito will send out a verification email/SMS to verify the identity.
  • CustomMessage_AdminCreateUser - When the user is created with adminUserCreate() API from Cognito, the invitation email with temporary password is sent.
  • CustomMessage_ResendCode - When the user requests for the code to be resent.
  • CustomMessage_ForgotPassword - When user initiates a forgot password, a verification code would be sent over email/SMS to the verified identity.
  • CustomMessage_UpdateUserAttribute - Whenever the user's attribute is updated.
  • CustomMessage_VerifyUserAttribute - When the attribute (email address or mobile number) is changed, it has to be verified.
  • CustomMessage_Authentication - For MFA authentication code email and SMS message.

Sample event for Lambda function

{
  "version": "1",
  "region": "us-east-1",
  "userPoolId": "us-east-1_xxxxxx",
  "userName": "xxxx@xxxx.com",
  "callerContext": {
    "awsSdkVersion": "aws-sdk-xxxx-2.22.1",
    "clientId": "xxxxxxxxxxxxxxxxx"
  },
  "triggerSource": "CustomMessage_ForgotPassword",
  "request": {
    "userAttributes": {
      "sub": "xxxxxxx",
      "cognito:user_status": "CONFIRMED",
      "email_verified": "true",
      "phone_number_verified": "true",
      "phone_number": "+1234567890",
      "preferred_username": "+1234567890",
      "email": "xxxxxxx@xxxxxxx.com"
    },
    "codeParameter": "{####}",
    "linkParameter": "{##Click Here##}",
    "usernameParameter": "xxxxx"
  },
  "response": {
    "smsMessage": null,
    "emailMessage": null,
    "emailSubject": null
  }
}
Enter fullscreen mode Exit fullscreen mode

Sample Lambda function code

'use strict';

const generate_email_body = (emailBody) => `
    <html>
        <body>
            <table align="center"  cellpadding="0" cellspacing="0" width="600" >
                <tr>
                    <td bgcolor="#ffffff" style="padding: 40px 0 30px 0;"><img src="" alt="Logo"  height="230" style="display: block;"></td>
                </tr>
                <tr>
                    <td bgcolor="#ffffff"><p style="margin: 0;">${emailBody}</p></td>
                </tr>
                <tr>
                    <td bgcolor="#ffffff" style="font-weight: 500; font-size: 11px"><p>Β© Copyright ${new Date().getFullYear()}. All Rights Reserved.</p></td>
                </tr>
            </table>
        </body>
    </html>
`

const sign_up_message = async(event) => {
    let email = event.request.usernameParameter;
    let code = event.request.codeParameter;
    event.response = {
        emailSubject: "Confirm your sign up",
        emailMessage: generate_email_body("<p>Your username is " + email + " and password is " + code + "</p>")
    }
    return event
}
const admin_create_user_message = async(event) => {
    let email = event.request.usernameParameter;
    let code = event.request.codeParameter;
    event.response = {
        emailSubject: "Your temporary password",
        emailMessage: generate_email_body("<p>Your username is " + email + " and password is " + code + "</p>")
    }
    return event
}
const resend_code_message = async(event) => {
    let email = event.request.usernameParameter;
    let code = event.request.codeParameter;
    event.response = {
        emailSubject: "Resend code",
        emailMessage: generate_email_body("<p>Your username is " + email + " and code is " + code + "</p>")
    }
    return event
}
const forgot_password = async(event) => {
    let email = event.request.usernameParameter;
    let code = event.request.codeParameter;
    event.response = {
        emailSubject: "Forgot password",
        emailMessage: generate_email_body("<p>Your forgot password code is " + code + "</p>")
    }
    return event
}
const update_user_attribute_message = async(event) => {
    let email = event.request.usernameParameter;
    let code = event.request.codeParameter;
    event.response = {
        emailSubject: "User updated",
        emailMessage: generate_email_body("<p>Your username is " + email + "</p>")
    }
    return event
}
const verify_user_attribute = async(event) => {
    let email = event.request.usernameParameter;
    let code = event.request.codeParameter;
    event.response = {
        emailSubject: "Verify user attribute",
        emailMessage: generate_email_body("<p>Your username is " + email + "</p>")
    }
    return event
}
const authenitcation_message = async(event) => {
    let email = event.request.usernameParameter;
    let code = event.request.codeParameter;
    event.response = {
        emailSubject: "MFA Authenitcation",
        emailMessage: generate_email_body("<p>Your username is " + email + " and code is " + code + "</p>")
    }
    return event
}
exports.handler = async(event) => {
    switch (event.triggerSource) {
        case "CustomMessage_SignUp": //Sign-up trigger whenever a new user signs him/herself up.
            return sign_up_message(event)
        case "CustomMessage_AdminCreateUser": //When the user is created with adminCreateUser() API
            return admin_create_user_message(event)
        case "CustomMessage_ResendCode": //When user requests the code again.
            return resend_code_message(event)
        case "CustomMessage_ForgotPassword": //Forgot password request initiated by user
            return forgot_password(event)
        case "CustomMessage_UpdateUserAttribute": //Whenever the user attributes are updated
            return update_user_attribute_message(event)
        case "CustomMessage_VerifyUserAttribute": //Verify mobile number/email
            return verify_user_attribute(event)
        case "CustomMessage_Authentication": //MFA authenitcation code.
            return authenitcation_message(event)
        default:
            return event

    }
};

Enter fullscreen mode Exit fullscreen mode

To test it out, you can head to console, and create a user with send invitation checked. On creating a user, the email address used would get the below email.
Invite email

Top comments (7)

Collapse
 
cbouvier15 profile image
Christian Bouvier

Thanks! Really useful!

Collapse
 
zachjonesnoel profile image
Jones Zachariah Noel

Thanks Christian! πŸ™Œ It's been a while I authored about Cognito, anything specific you were looking for?

Collapse
 
jacksonkasi profile image
Jackson Kasi

hi @zachjonesnoel,
really thanks for share with us.

can you please tell or give me a reference, how can I use a third-party email or sms provider in cognito?

I like to integrate SendGrid. how can i do this? in node js lambda

Collapse
 
zachjonesnoel profile image
Jones Zachariah Noel

Hey Jackson Kasi,
Thanks for the feedback.

Well I did try integrating with SendGrid. I don't remember what was the attribute but I will check for my archives around it and share it with you. Luckily I did try it with Lambda fn on NodeJS runtime.

Collapse
 
jacksonkasi profile image
Jackson Kasi • Edited

thanks for your reply ✨ I have tried, but

  • the secret code is decoded successfully in the local system.
  • but this same function I have run in lambda. that time only I face KMS + Lambda related problem.

I have done the following article

thelambdablog.com/how-to-decrypt-a...

blog.xiggit.com/blog/how-we-use-cu...

quiz: repost.aws/questions/QUQdWAxm0DTJG...

Thread Thread
 
zachjonesnoel profile image
Jones Zachariah Noel

Hey Jackson,

Did some searching, but I had used SendGrid based emails out of Cognito. Luckily Googling out resulted in a blog post about how SendGrid could be used for Cognito's custom messages - maxivanov.io/send-aws-cognito-emai... and also AWS docs - docs.aws.amazon.com/cognito/latest...

Key things to ensure,

  • Cognito is suppressing emails by default.
  • Your Lambda fn has access to kms:CreateGrant. (Looks like that's the error you have posted on repost.aws)
Thread Thread
 
jacksonkasi profile image
Jackson Kasi

yeah! i just follow the AWS doc. that policy I applied in aws kms- CMK. but still the same error. so now i raised a ticket 🎫 in aws. Doc: docs.aws.amazon.com/cognito/latest...