Menu
Amazon Cognito
Developer Guide (Version Last Updated: 08/26/2017)

Customizing User Pool Workflows by Using AWS Lambda Triggers

You can use AWS Lambda triggers with Amazon Cognito user pools to customize workflows at various stages in the lifecycle of a user account. For more information, see the AWS Lambda Developer Guide.

Important

When called, your Lambda function must respond within 5 seconds. If it does not, Amazon Cognito retries the call. After 3 unsuccessful attempts, Amazon Cognito times out. This 5-second timeout value cannot be changed.

The following Lambda triggers are available for you to implement:

Pre sign-up

Amazon Cognito invokes this trigger when a user attempts to register (sign up), allowing you to perform custom validation to accept or deny the registration request.

Pre authentication

Amazon Cognito invokes this trigger when a user attempts to authenticate (sign in), allowing you to perform custom validation to accept or deny the authentication request.

Custom message

Amazon Cognito invokes this trigger before sending an email or phone verification message or a multi-factor authentication (MFA) code, allowing you to customize the message dynamically. Static custom messages can be edited in the Message Customizations tab of the Amazon Cognito console.

Post authentication

Amazon Cognito invokes this trigger after authenticating a user, allowing you to add custom logic.

Post confirmation

Amazon Cognito invokes this trigger after a user is confirmed, allowing you to send custom messages or to add custom logic. For example, you may want to implement analytics in your app.

Define Auth Challenge

Amazon Cognito invokes this trigger to initiate the custom authentication flow.

Create Auth Challenge

Amazon Cognito invokes this trigger after Define Auth Challenge if a custom challenge has been specified as part of the Define Auth Challenge trigger.

Verify Auth Challenge Response

Amazon Cognito invokes this trigger to verify if the response from the end user for a custom Auth Challenge is valid or not.

Creating an AWS Lambda Trigger for a Stage

You can create an AWS Lambda function and then associate that function with one of the user account life cycle stages to create a Lambda trigger.

To add a Lambda function to a user stage

  1. If you haven't done so already, create a Lambda function using the Lambda console.

  2. Navigate to the Amazon Cognito console, choose Manage User Pools, and then choose the user pool to add the Lambda function to.

  3. In your user pool, choose the Triggers tab.

  4. Associate a user stage with a Lambda function by choosing the function from the drop-down menu for that stage, and then save your changes.

AWS Lambda Trigger Request and Response Parameters

This section describes the AWS Lambda trigger request and response parameters.

AWS Lambda Trigger Common Parameters

The event information passed to the invoked Lambda function contains the parameters that were passed from the Amazon Cognito service. The general format of the event is shown next. The request and the response parameters depend on the Lambda trigger.

Copy
{ "version": number, "triggerSource": "string", "region": AWSRegion, "userPoolId": "string", "callerContext": { "awsSdkVersion": "string", "clientId": "string" }, "request": { "userAttributes": { "string": "string", .... } }, "response": {} }
version

The version number of your Lambda function.

triggerSource

The name of the event that triggered the Lambda function. The following table shows the triggerSource values and the triggering event for each value.

triggerSource value Triggering event
PreSignUp_SignUp Pre-sign up
PostConfirmation_ConfirmSignUp Post sign-up confirmation
PostConfirmation_ConfirmForgotPassword Post Forgot Password confirmation
PreAuthentication_Authentication Pre authentication
PostAuthentication_Authentication Post authentication
CustomMessage_SignUp Custom message – To send the confirmation code post sign-up
CustomMessage_AdminCreateUser Custom message – To send the temporary password to a new user
CustomMessage_ResendCode Custom message – To resend the confirmation code to an existing user
CustomMessage_ForgotPassword Custom message – To send the confirmation code for Forgot Password request
CustomMessage_UpdateUserAttribute Custom message – When a user's email or phone number is changed, this trigger sends a verification code automatically to the user. Cannot be used for other attributes.
CustomMessage_VerifyUserAttribute Custom message – This trigger sends a verification code to the user when the they manually request it for a new email or phone number.
CustomMessage_Authentication Custom message – To send MFA code during authentication
DefineAuthChallenge_Authentication Define Auth Challenge
CreateAuthChallenge_Authentication Create Auth Challenge
VerifyAuthChallengeResponse_Authentication Verify Auth Challenge Response
region

The AWS Region, as an AWSRegion instance.

userPoolId

The user pool ID for the user pool.

callerContext

The caller context, which consists of the following:

awsSdkVersion

The AWS SDK version number.

clientId

The ID of the client associated with the user pool.

request

The request from the Amazon Cognito service. This request must include:

userAttributes

One or more pairs of user attribute names and values. Each pair is in the form "name": "value".

response

The response from your Lambda trigger. The return parameters depend on the triggering event.

Pre Sign-up Lambda Parameters

The request includes validation data from the client.

Copy
"request": { "userAttributes": { "string": "string", .... }, "validationData": {<validation data as key-value (String, String) pairs, from the client>} }
userAttributes

One or more name-value pairs representing user attributes. The attribute names are the keys.

validationData

One or more name-value pairs containing the validation data in the request to register a user. The validation data is set and then passed from the client in the request to register a user.

In the response, you can set autoConfirmUser to true if you want to auto-confirm the user. You can set autoVerifyEmail to true to auto-verify the user's email. You can set autoVerifyPhone to true to auto-verify the user's phone number.

Copy
"response": { "autoConfirmUser": boolean "autoVerifyEmail": boolean "autoVerifyPhone": boolean }
autoConfirmUser

Set to true to auto-confirm the user, or false otherwise.

autoVerifyEmail

Set to true to set as verified the email of a user who is signing up, or false otherwise. If autoVerifyEmail is set to true, the email attribute must have a valid, non-null value. Otherwise an error will occur and the user will not be able to complete sign-up.

If the email attribute is selected as an alias, an alias will be created for the user's email when autoVerifyEmail is set. If an alias with that email already exists, the alias will be moved to the new user and the previous user's email will be marked as unverified. For more information, see Overview of Aliases.

autoVerifyPhone

Set to true to set as verified the phone number of a user who is signing up, or false otherwise. If autoVerifyPhone is set to true, the phone_number attribute must have a valid, non-null value. Otherwise an error will occur and the user will not be able to complete sign-up.

If the phone_number attribute is selected as an alias, an alias will be created for the user's phone number when autoVerifyPhone is set. If an alias with that phone number already exist, the alias will be moved to the new user and the previous user's phone number will be marked as unverified. For more information, see Overview of Aliases.

Pre-Authentication Lambda Parameters

The request includes validation data from the client.

Copy
"request": { "userAttributes": { "string": "string", .... }, "validationData": {<validation data as key-value (String, String) pairs, from the client>} }
userAttributes

One or more name-value pairs representing user attributes.

validationData

One or more key-value pairs containing the validation data in the user's sign-in request.

No return information is expected in the response.

Copy
"response": { }

Custom Message Lambda Parameters

The request includes codeParameter, which is a string that acts as a placeholder for the code that's being delivered to the user. Insert the codeParameter string into the message body, at the position where you want the verification code to be inserted. On receiving this response, the Amazon Cognito service replaces the codeParameter string with the actual verification code.

Copy
"request": { "userAttributes": { "string": "string", .... }, "codeParameter": "string" }
userAttributes

One or more name-value pairs representing user attributes.

codeParameter

A string for you to use as the placeholder for the verification code in the custom message.

In the response, you specify the custom text to use in messages to your users.

Copy
"response": { "smsMessage": "string", "emailMessage": "string", "emailSubject": "string"; }
smsMessage

The custom SMS message to be sent to your users. Must include the codeParameter value received in the request.

emailMessage

The custom email message to be sent to your users. Must include the codeParameter value received in the request.

emailSubject

The subject line for the custom message.

Post-Authentication Lambda Parameters

The request includes the following:

  • newDeviceUsed flag – indicates if the user has signed in on a new device

The newDeviceUsed flag is set only if the remembered devices value of the user pool is set to Always or User Opt-In.

Copy
"request": { "userAttributes": { "string": "string", .... }, "newDeviceUsed": boolean }
userAttributes

One or more name-value pairs representing user attributes.

No return information is expected in the response.

Copy
"response": { }

Post-Confirmation Lambda Parameters

The request contains the current attributes for the confirmed user.

Copy
"request": { "userAttributes": { "string": "string", .... } }
userAttributes

One or more name-value pairs representing user attributes.

No return information is expected in the response.

Copy
"response": { }

Define Auth Challenge Lambda Parameters

The request contains session, which is an array containing all of the challenges that are presented to the user in the authentication process that is underway, along with the corresponding result. The challenge details (ChallengeResult) are stored in chronological order in the session array, with session[0] representing the first challenge that is presented to the user.

Copy
"request": { "userAttributes": { "string": "string", .... }, "session": { [ ChallengeResult ] } }
userAttributes

One or more name-value pairs representing user attributes.

session

The session element is an array of ChallengeResult elements, each of which contains the following elements:

challengeName

The challenge type. One of: "CUSTOM_CHALLENGE", "PASSWORD_VERIFIER", "SMS_MFA", "DEVICE_SRP_AUTH", "DEVICE_PASSWORD_VERIFIER", or "ADMIN_NO_SRP_AUTH".

challengeResult

Set to true if the user successfully completed the challenge, or false otherwise.

challengeMetaData

Your name for the custom challenge. Used only if challengeName is "CUSTOM_CHALLENGE".

In the response you can return the next stage of the authentication process.

Copy
"response": { "challengeName": "string", "issueTokens": boolean, "failAuthentication": boolean }
challengeName

A string containing the name of the next challenge. If you want to present a new challenge to your user, specify the challenge name here.

issueTokens

Set to true if you determine that the user has sufficiently authenticated by completing the challenges, or false otherwise.

failAuthentication

Set to true if you want to terminate the current authentication process, or false otherwise.

Create Auth Challenge Lambda Parameters

This Lambda trigger is invoked to create a challenge to present to the user. The request for this Lambda trigger includes the challengeName and session. The challengeName is a string and is the name of the next challenge to the user. The value of this attribute is set in the Define Auth Challenge Lambda trigger.

Copy
"request": { "userAttributes": { "string": "string", .... }, "challengeName": "string", "session": { [ ChallengeResult ] } }
userAttributes

One or more name-value pairs representing user attributes.

challengeName

The name of the new challenge.

session

The session element is an array of ChallengeResult elements, each of which contains the following elements:

challengeName

The challenge type. One of: "CUSTOM_CHALLENGE", "PASSWORD_VERIFIER", "SMS_MFA", "DEVICE_SRP_AUTH", "DEVICE_PASSWORD_VERIFIER", or "ADMIN_NO_SRP_AUTH".

challengeResult

Set to true if the user successfully completed the challenge, or false otherwise.

challengeMetaData

Your name for the custom challenge. Used only if challengeName is "CUSTOM_CHALLENGE".

The challenge parameters for the new challenge are added to the response.

Copy
"response": { "publicChallengeParameters": { "string": "string", .... }, "privateChallengeParameters": { "string": "string", .... }, "challengeMetadata": "string" }
publicChallengeParameters

One or more key-value pairs for the client app to use in the challenge to be presented to the user. This parameter should contain all of the necessary information to accurately present the challenge to the user.

privateChallengeParameters

This parameter is only used by the Verify Auth Challenge Response Lambda trigger. This parameter should contain all of the information that is required to validate the user's response to the challenge. In other words, the publicChallengeParameters parameter contains the question that is presented to the user and privateChallengeParameters contains the valid answers for the question.

challengeMetadata

Your name for the custom challenge, if this is a custom challenge.

Verify Auth Challenge Response Lambda Parameters

The request for this trigger contains the privateChallengeParameters and challengeAnswer parameters. The privateChallengeParameters values are returned by the Create Auth Challenge Lambda trigger and will contain the expected response from the user. The challengeAnswer parameter contains the user's response for the challenge.

Copy
"request": { "userAttributes": { "string": "string", .... }, "privateChallengeParameters": { "string": "string", .... }, "challengeAnswer": { "string": "string", .... } }
userAttributes

One or more name-value pairs representing user attributes.

privateChallengeParameters

This parameter is only used by the Verify Auth Challenge Response Lambda trigger. This parameter should contain all of the information that is required to validate the user's response to the challenge. In other words, the publicChallengeParameters parameter contains the question that is presented to the user and privateChallengeParameters contains the valid answers for the question.

challengeAnswer

The answer in the user's response to the challenge.

The response contains the answerCorrect attribute, which is set to true if the user successfully completed the challenge, or false otherwise.

Copy
"response": { "answerCorrect": boolean }
answerCorrect

Set to true if the user has successfully completed the challenge, or false otherwise.

AWS Lambda Trigger Examples

This section gives code examples for each type of AWS Lambda trigger.

Pre Sign-up Example #1: Auto-Confirm the User

The following example initializes just before the service starts the new user registration process. With this Lambda function, you can add custom logic to validate, filter, or restrict the types of user accounts that can be registered. For example, you may only want to allow users to register if they have been invited to join the service. This example uses the autoConfirmUser flag to indicate whether to auto-confirm a user to the user pool.

Copy
exports.handler = function(event, context) { // This Lambda function returns a flag to indicate if a user should be auto-confirmed. // Perform any necessary validations. // Impose a condition that the minimum length of the username of 5 is imposed on all user pools. if (event.userName.length < 5) { var error = new Error('failed!'); context.done(error, event); } // Access your resource which contains the list of emails of users who were invited to sign up // Compare the list of email IDs from the request to the approved list if(event.userPoolId === "yourSpecialUserPool") { if (event.request.userAttributes.email in listOfEmailsInvited) { event.response.autoConfirmUser = true; } } // Return result to Cognito context.done(null, event); }; { "version": 1, "triggerSource": "PreSignUp_SignUp", "region": "<region>", "userPoolId": "<userPoolId>", "userName": "<userName>", "callerContext": { "awsSdk": "<calling aws sdk with version>", "clientId": "<apps client id>", ... }, "request": { "userAttributes": { "email": "<email>", "phone_number": "<phone_number>", ... }, "validationData": { "k1": "v1", "k2": "v2", ... } }, "response": { "autoConfirmUser": false } }

Pre Sign-up Example #2: Auto-Confirm and Auto-Verify the User

The following example is similar to Example #1, except that it automatically confirms the user and automatically sets the user's email and phone_number attributes to verified if the attribute is present.

If aliasing is enabled, aliases will be created for phone_number and email when auto-verify is set. If an alias with the same phone number already exists, the alias will be moved to the new user, and the previous user's phone_number will be marked as unverified. The same is true for email addresses. If this is not the desired behavior, you can use the ListUsers API to see if there is an existing user who is already using the new user's phone number or email address as an alias.

Copy
exports.handler = (event, context, callback) => { //console.log('Received event:', JSON.stringify(event, null, 2)); // TODO Confirm this is a user that should be auto-confirmed, e.g., has a valid token in event.request.validationData var autoConfirm = true; if (autoConfirm) { event.response.autoConfirmUser = true; console.log('Auto confirmed user'); if (event.request.userAttributes.hasOwnProperty("email")) { event.response.autoVerifyEmail = true; console.log('Set email verified'); } if (event.request.userAttributes.hasOwnProperty("phone_number")) { event.response.autoVerifyPhone = true; console.log('Set phone_number verified'); } } callback(null, event); };

Pre Authentication Example

This sample function restricts users from a specific app client ID from authenticating.

Copy
exports.handler = function(event, context) { if (event.callerContext.clientId === "<client id to be blocked>") { var error = new Error('Cannot authenticate users from this client'); context.done(error, event); } context.done(null, event); };

Sample event parameter:

Copy
{ "version": 1, "triggerSource": "PreAuthentication_Authentication", "region": "<region>", "userPoolId": "<userPoolId>", "userName": "<userName>", "callerContext": { "awsSdkVersion": "<calling AWS sdk with version>", "clientId": "<apps client id>", ... }, "request": { "userAttributes": { "phone_number_verified": false, "email_verified": false, ... // All custom attributes }, "validationData": { "k1": "v1", "k2": "v2", ... } }, "response": {} }

Custom Message Example

This Lambda function is invoked when the service requires an app to send a verification code to the user. This function is used to customize the messages that are sent to deliver the code.

This Lambda trigger is invoked at multiple points: post-registration; resending a verification code; forgotten password; or verifying a user attribute. The response includes messages for both SMS and email. The message must include the code parameter, {####}, which is the placeholder for the verification code that is delivered to the user.

For email, the maximum length for the message is 20,000 UTF-8 characters, including the verification code. HTML tags can be used in these emails. For SMS, the maximum length is 140 UTF-8 characters, including the verification code.

Copy
exports.handler = function(event, context) { // if(event.userPoolId === "theSpecialUserPool") { // Identify why was this function invoked if(event.triggerSource === "CustomMessage_SignUp") { // Ensure that your message contains event.request.codeParameter. This is the placeholder for code that will be sent event.response.smsMessage = "Welcome to the service. Your confirmation code is " + event.request.codeParameter; event.response.emailSubject = "Welcome to the service"; event.response.emailMessage = "Thank you for signing up. " + event.request.codeParameter + " is your verification code"; } // Create custom message for other events } // Customize messages for other user pools // // Return result to Cognito context.done(null, event); };

Sample event parameter:

Copy
{ "version": 1, "triggerSource": "CustomMessage_SignUp/CustomMessage_ResendCode/CustomMessage_ForgotPassword/CustomMessage_VerifyUserAttribute", "region": "<region>", "userPoolId": "<userPoolId>", "userName": "<userName>", "callerContext": { "awsSdk": "<calling aws sdk with version>", "clientId": "<apps client id>", ... }, "request": { "userAttributes": { "phone_number_verified": false, "email_verified": true, ... }, "codeParameter": "####" }, "response": { "smsMessage": "<custom message to be sent in the message with code parameter>" "emailMessage": "<custom message to be sent in the message with code parameter>" "emailSubject": "<custom email subject>" } }

Post Authentication Example

This function is invoked after a user is successfully authenticated. This sample function logs in to the console after a user is authenticated.

Copy
exports.handler = (event, context, callback) => { console.log('User authenticated: User-Pool', event.userPoolId+", UserId:" + event.userName); // Return result to Amazon Cognito context.done(null, event); };

Sample event parameter:

Copy
{ "version": 1, "triggerSource": "PostAuthentication_Authentication", "region": "<region>", "userPoolId": "<userPoolId>", "userName": "<userName>", "callerContext": { "awsSdk": "<calling aws sdk with version>", "clientId": "<apps client id>", ... }, "request": { "userAttributes": { "phone_number_verified": true, "email_verified": true, ... //all custom attributes } }, "response": {} };

Post Confirmation Example

The example sends an email message to inform the user that he or she has been confirmed.

Copy
var aws = require('aws-sdk'); var ses = new aws.SES(); exports.handler = function(event, context) { console.log(event); if (event.request.userAttributes.email) { sendEmail(event.request.userAttributes.email, "Congratulations "+event.userName+", you have been confirmed: ", function(status) { context.done(null, event); }); } else { // Nothing to do, the user's email ID is unknown context.done(null, event); } }; function sendEmail(to, body, completedCallback) { var eParams = { Destination: { ToAddresses: [to] }, Message: { Body: { Text: { Data: body } }, Subject: { Data: "Cognito Identity Provider registration completed" } }, Source: "<source_email>" }; var email = ses.sendEmail(eParams, function(err, data){ if (err) { console.log(err); } else { console.log("===EMAIL SENT==="); } completedCallback('Email sent'); }); console.log("EMAIL CODE END"); };

Sample event parameter:

Copy
{ "version": 1, "triggerSource": "PostConfirmation_ConfirmSignUp", "region": "<region>", "userPoolId": "<userPoolId>", "userName": "<userName>", "callerContext": { "awsSdk": "<calling aws sdk with version>", "clientId": "<apps client id>", ... }, "request": { "userAttributes" : { "email": "<email>", "phone_number": "<phone_number>", ... } }, "response": {} }

Define Auth Challenge Example

This example defines a series of challenges for authentication and issues tokens only if all of the challenges are successfully completed.

Copy
exports.handler = function(event, context) { if (event.request.session.length == 1 && event.request.session[0].challengeName == 'SRP_A') { event.response.issueTokens = false; event.response.failAuthentication = false; event.response.challengeName = 'PASSWORD_VERIFIER'; } else if (event.request.session.length == 2 && event.request.session[1].challengeName == 'PASSWORD_VERIFIER' && event.request.session[1].challengeResult == true) { event.response.issueTokens = false; event.response.failAuthentication = false; event.response.challengeName = 'CUSTOM_CHALLENGE'; } else if (event.request.session.length == 3 && event.request.session[2].challengeName == 'CUSTOM_CHALLENGE' && event.request.session[2].challengeResult == true) { event.response.issueTokens = true; event.response.failAuthentication = false; } else { event.response.issueTokens = false; event.response.failAuthentication = true; } context.done(null, event); }

Create Auth Challenge Example

A CAPTCHA is created as a challenge to the user. The URL for the CAPTCHA image is added to the public challenge parameters as "captchaUrl", and the expected answer is added to the private challenge parameters.

Copy
exports.handler = function(event, context) { if (event.request.challengeName == 'CUSTOM_CHALLENGE') { event.response.publicChallengeParameters = {}; event.response.publicChallengeParameters.captchaUrl = 'url/123.jpg' event.response.privateChallengeParameters = {}; event.response.privateChallengeParameters.answer = '5'; event.response.challengeMetadata = 'CAPTCHA_CHALLENGE'; } context.done(null, event); }

Verify Auth Challenge Response Example

In this example, the Lambda function checks whether the user's response to a challenge matches the expected response. The answerCorrect parameter is set to true if the user's response matches the expected response.

Copy
exports.handler = function(event, context) { if (event.request.privateChallengeParameters.answer == event.request.challengeAnswer) { event.response.answerCorrect = true; } else { event.response.answerCorrect = false; } context.done(null, event); }