Guides & tutorials
LoginSign Up


How to create Lambda triggers to use Custom Auth flows with Amazon Cognito

In this tutorial, we will cover how to create Lambda functions for custom authentication flows. This is useful if you want to:

  • Automatically log in a user once they sign up.
  • Create passwordless flows.

The approach we will follow with these Lambda functions assume that this is a first-time login in a signup flow or that you have a custom flow that authenticates the user. If you don’t have any scenarios yet, have a look at our templates.

1. Create Lambda functions

Go to your Lambda console, where we will create 3 Lambda functions:

1.1 Define auth challenge function

Create the first function, name it “defineCustomAuthChallenge” and add the following code:

function isArenguChallenge(cr) {
    return cr.challengeName === 'CUSTOM_CHALLENGE'
        && cr.challengeMetadata === 'ARENGU_CLAIM_JWT';

exports.handler = async (event) => {

    const userFound = event.request.userNotFound === false;

    if (!userFound) {
        event.response.failAuthentication = true;
        return event;

    const noChallenges = !event.request.session || event.request.session.length === 0;
    if (noChallenges) {
        event.response.challengeName = 'CUSTOM_CHALLENGE';
        return event;

    const arenguChallenge = event.request.session.find((cr) => isArenguChallenge((cr)));
    if (!arenguChallenge) {
        event.response.failAuthentication = true;
        return event;
    event.response.issueTokens = arenguChallenge.challengeResult;
    return event;

1.2 Create auth challenge function

Create the second function, name it “createCustomAuthChallenge” and add the following code:

exports.handler = async (event) => {

    event.response = {
        challengeMetadata: 'ARENGU_CLAIM_JWT',
        // Cognito requires at least one public param
        publicChallengeParameters: {
            "jwt": "required"
        privateChallengeParameters: {
            "arengu_challenge": "claim_jwt"

    return event;

1.3 Verify auth challenge response function

Create the third function, name it “verifyCustomAuthChallenge” and add the following code:

const JWT_SECRET = process.env.JWT_SECRET;
const jwt = require('jsonwebtoken');

exports.handler = async (event) => {
  const arenguChallenge = event.request.privateChallengeParameters
      && event.request.privateChallengeParameters.arengu_challenge === 'claim_jwt';

  if (!arenguChallenge) {
      event.response.answerCorrect = false;
      return event;
  try {
    const decodedJwt = jwt.verify(event.request.challengeAnswer, JWT_SECRET);
    if (decodedJwt.sub === event.request.userAttributes.sub) {
      event.response.answerCorrect = true;
    } else {
      event.response.answerCorrect = false;
  } catch(err) {
    event.response.answerCorrect = false;

  return event;
This Lambda function requires installing the "jsonwebtoken" node module. You can directly upload this .zip that includes the module.

As we are using JSON Web Tokens (JWT) to communicate with Amazon Cognito, we need to create a secret key to sign the JWT. Go to Configuration -> Environment variables -> Edit and add a variable with Key “JWT_SECRET_KEY” and a long random string as Value.

2. Add Lambda triggers to your Cognito user pool

Add a Lambda trigger under your User pool properties

Click on Add Lambda trigger

  • Select “Custom authentication
  • Select “Define auth challenge
  • Select “defineCustomAuthChallenge” lambda function

Create 2 additional Lambda triggers with the 2 remaining Lambdas functions:

  1. Create auth challenge -> createCustomAuthChallenge
  2. Verify auth challenge response -> verifyCustomAuthChallenge

3. Create custom JWTs to log in users

Once your Lambda triggers are created, you login users by generating custom JWTs in your backend with the following information:

  • Secret or private key: the same secret from the "Verify auth challenge response" Lambda function.
  • Subject: the sub of the user (eg. 05975eb2-136b-44af-9834-b3d2b7e22ae5)

And using the Amplify SDK with the following methods:

import { Auth } from "aws-amplify";

  // other configurations
  // ...
  authenticationFlowType: "CUSTOM_AUTH"

const username = "YOUR_USER_USERNAME";
const token = "YOUR_GENERATED_JWT";

  .then(user => {
    Auth.sendCustomChallengeAnswer(user, token)
      .then(o => console.log(o))
      .catch(err => console.log(err));
  .catch(err => console.log(err));

In Arengu, and if you've started from a template, you will only need to add the secret to the "Sign JSON web token" action:

And configure the Ending screen settings, that will automatically use the Amplify SDK if it's configured in your site:

Table of contents