Cognito Custom Auth Flow: Create auth challenge lambda function is triggered multiple time

0

I'm trying to implement passwordless authentication in Cognito using lambda triggers. I've implemented the three lambda functions:

  • DefineAuthChallenge
  • CreateAuthChallenge
  • VerifyAuthChallenge

The issue is when I'm invoking initiateAuth API multiple events trigger the CreateAuthChallenge lambda. Hence, causing the user to receive more than one OTP for a given request. Below is the implementation of CreateAuthChallenge lambda.

` public class CreateAuthChallengeHandler implements RequestStreamHandler { private static final String SENDER_EMAIL = "user@gmail.com"; private static final String SUBJECT = "OTP"; public ObjectMapper objectMapper = new ObjectMapper();

@Override
public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
    LambdaLogger logger = context.getLogger();
    JsonNode mainNode = objectMapper.readTree(input);
    logger.log("input: " + mainNode.toString());
    JsonNode session = mainNode.get("request").get("session");
    JsonNode userAttributes = mainNode.get("request").get("userAttributes");
    JsonNode responseNode = mainNode.get("response");
    int sessionLength = objectMapper.convertValue(session, ArrayList.class).size();
    String secretCode;
    if (sessionLength == 0) {
        logger.log("sessionLength: " + sessionLength);
        secretCode = getSecretCode();
        SesClient sesClient = SesClient.builder().region(Region.AP_SOUTH_1).build();
        try {
            logger.log("sending email ...");
            SendEmailRequest emailRequest = SendEmailRequest.builder()
                    .source(SENDER_EMAIL)
                    .destination(Destination.builder().toAddresses(userAttributes.get("email").asText()).build())
                    .message(Message.builder()
                            .subject(Content.builder().data(SUBJECT).build())
                            .body(Body.builder().text(Content.builder().data(secretCode).build()).build()).build())
                    .build();
            SendEmailResponse sendEmailResponse = sesClient.sendEmail(emailRequest);
            logger.log("sendEmailResult: " + sendEmailResponse.messageId());
        } catch (SesException e) {
            logger.log("Email sending failed. Error message: " + e.getMessage());
        } finally {
            sesClient.close();
        }
    } else {
        JsonNode previousChallenge = session.get(sessionLength - 1);
        secretCode = previousChallenge.get("challengeMetadata").asText();
        logger.log("secretCode: " + secretCode);
    }

    ((ObjectNode) responseNode).putPOJO("publicChallengeParameters", Map.of(
            "email", userAttributes.get("email").asText()));
    ((ObjectNode) responseNode).putPOJO("privateChallengeParameters", Map.of(
            "secretLoginCode", secretCode));
    ((ObjectNode) responseNode).put("challengeMetadata", secretCode);
    objectMapper.writeValue(output, mainNode);
    logger.log("output: " + output.toString());
}

} `

pom.xml

`

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>

<groupId>XXXXXXXX</groupId>
<artifactId>XXXXXXX</artifactId>
<version>4.7-SNAPSHOT</version>

<properties>
    <maven.compiler.source>21</maven.compiler.source>
    <maven.compiler.target>21</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-lambda-java-core</artifactId>
        <version>1.2.3</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.17.0</version>
    </dependency>
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>ses</artifactId>
        <version>2.25.40</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>9</source>
                <target>9</target>
            </configuration>
        </plugin>
    </plugins>
</build>
</project> `

Below are DefineAuthChallenge are logs: 2024-04-30T17:51:29.041+05:30 INIT_START Runtime Version: java:21.v15 Runtime Version ARN: arn:aws:lambda:ap-south-1::runtime:XXXXXX 2024-04-30T17:51:29.709+05:30 START RequestId: 81165b64-2ee5-4d40-83df-a3fc21faa856 Version: $LATEST 2024-04-30T17:51:30.032+05:30 input: {"version":"1","region":"ap-south-1","userPoolId":"XXXXXX","userName":"XXXXXX","callerContext":{"awsSdkVersion":"aws-sdk-java-1.12.641","clientId":"XXXXXX"},"triggerSource":"DefineAuthChallenge_Authentication","request":{"userAttributes":{"sub":"f113dd3a-1021-7084-2495-8c4eb4853463","email_verified":"True","custom:login-path":"XXXXXX","cognito:user_status":"CONFIRMED","name":"XXXXXX","email":"XXXXXX"},"session":[],"userNotFound":false},"response":{"challengeName":null,"issueTokens":null,"failAuthentication":null}} 2024-04-30T17:51:30.230+05:30 output: {"version":"1","region":"ap-south-1","userPoolId":"XXXXXX","userName":"XXXXXX","callerContext":{"awsSdkVersion":"aws-sdk-java-1.12.641","clientId":"XXXXXX"},"triggerSource":"DefineAuthChallenge_Authentication","request":{"userAttributes":{"sub":"f113dd3a-1021-7084-2495-8c4eb4853463","email_verified":"True","custom:login-path":"XXXXXX","cognito:user_status":"CONFIRMED","name":"XXXXXX","email":"XXXXXX"},"session":[],"userNotFound":false},"response":{"challengeName":"CUSTOM_CHALLENGE","issueTokens":false,"failAuthentication":false}} 2024-04-30T17:51:30.231+05:30 END RequestId: 81165b64-2ee5-4d40-83df-a3fc21faa856 2024-04-30T17:51:30.231+05:30 REPORT RequestId: 81165b64-2ee5-4d40-83df-a3fc21faa856 Duration: 521.66 ms Billed Duration: 522 ms Memory Size: 512 MB Max Memory Used: 111 MB Init Duration: 667.20 ms Below are the CreateAuthChallenge logs: 2024-04-30T17:51:35.423+05:30 INIT_START Runtime Version: java:21.v15 Runtime Version ARN: arn:aws:lambda:ap-south-1::runtime:XXXXXX 2024-04-30T17:51:36.085+05:30 START RequestId: a9efd773-08b6-4b4b-a2b3-d1fb7e3fb502 Version: $LATEST 2024-04-30T17:51:36.407+05:30 input: {"version":"1","region":"ap-south-1","userPoolId":"XXXX","userName":"user@gmail.com","callerContext":{"awsSdkVersion":"aws-sdk-java-1.12.641","clientId":"XXXXX"},"triggerSource":"CreateAuthChallenge_Authentication","request":{"userAttributes":{"sub":"XXXXXX","email_verified":"True","custom:login-path":"https://test.com","cognito:user_status":"CONFIRMED","name":"XXXXXXX","email":"XXXXXX"},"challengeName":"CUSTOM_CHALLENGE","session":[],"userNotFound":false},"response":{"publicChallengeParameters":null,"privateChallengeParameters":null,"challengeMetadata":null}} 2024-04-30T17:51:36.604+05:30 sessionLength: 0 2024-04-30T17:51:36.784+05:30 SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". 2024-04-30T17:51:36.784+05:30 SLF4J: Defaulting to no-operation (NOP) logger implementation 2024-04-30T17:51:36.784+05:30 SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. 2024-04-30T17:51:40.811+05:30 sending email ... 2024-04-30T17:51:43.649+05:30 sendEmailResult: 0109018f2ef42538-54f24435-4449-46c6-afb7-8750fbf5de56-000000 2024-04-30T17:51:43.710+05:30 output: {"version":"1","region":"ap-south-1","userPoolId":"XXXXXX","userName":"XXXXXX","callerContext":{"awsSdkVersion":"aws-sdk-java-1.12.641","clientId":"XXXXXX"},"triggerSource":"CreateAuthChallenge_Authentication","request":{"userAttributes":{"sub":"XXXXXX","email_verified":"True","custom:login-path":"https://XXXXXX","cognito:user_status":"CONFIRMED","name":"XXXXXX","email":"XXXXXX"},"challengeName":"CUSTOM_CHALLENGE","session":[],"userNotFound":false},"response":{"publicChallengeParameters":{"email":"XXXXXX"},"privateChallengeParameters":{"secretLoginCode":"6605"},"challengeMetadata":"6605"}} 2024-04-30T17:51:43.724+05:30 END RequestId: a9efd773-08b6-4b4b-a2b3-d1fb7e3fb502 2024-04-30T17:51:43.724+05:30 REPORT RequestId: a9efd773-08b6-4b4b-a2b3-d1fb7e3fb502 Duration: 7639.15 ms Billed Duration: 7640 ms Memory Size: 512 MB Max Memory Used: 169 MB Init Duration: 661.01 ms 2024-04-30T17:52:25.756+05:30 START RequestId: d39e6945-45a2-4f81-a0b3-c860afdb47d4 Version: $LATEST 2024-04-30T17:52:25.757+05:30 input: {"version":"1","region":"ap-south-1","userPoolId":"XXXXXX","userName":"XXXXXX","callerContext":{"awsSdkVersion":"aws-sdk-java-1.12.641","clientId":"XXXXXX"},"triggerSource":"CreateAuthChallenge_Authentication","request":{"userAttributes":{"sub":"XXXXXX","email_verified":"True","custom:login-path":"https://XXXXXX","cognito:user_status":"CONFIRMED","name":"XXXXXX","email":"XXXXXX"},"challengeName":"CUSTOM_CHALLENGE","session":[],"userNotFound":false},"response":{"publicChallengeParameters":null,"privateChallengeParameters":null,"challengeMetadata":null}} 2024-04-30T17:52:25.757+05:30 sessionLength: 0 2024-04-30T17:52:25.766+05:30 sending email ... 2024-04-30T17:52:25.958+05:30 sendEmailResult: 0109018f2ef4cb42-08000c0f-1d0f-411c-bc90-473fa1542e0d-000000 2024-04-30T17:52:25.965+05:30 output: {"version":"1","region":"ap-south-1","userPoolId":"XXXXXX","userName":"XXXXXX","callerContext":{"awsSdkVersion":"aws-sdk-java-1.12.641","clientId":"XXXXXX"},"triggerSource":"CreateAuthChallenge_Authentication","request":{"userAttributes":{"sub":"XXXXXX","email_verified":"True","custom:login-path":"https://XXXXXX","cognito:user_status":"CONFIRMED","name":"XXXXXX","email":"XXXXXX"},"challengeName":"CUSTOM_CHALLENGE","session":[],"userNotFound":false},"response":{"publicChallengeParameters":{"email":"XXXXXX"},"privateChallengeParameters":{"secretLoginCode":"5757"},"challengeMetadata":"5757"}} 2024-04-30T17:52:25.966+05:30 END RequestId: d39e6945-45a2-4f81-a0b3-c860afdb47d4 2024-04-30T17:52:25.966+05:30 REPORT RequestId: d39e6945-45a2-4f81-a0b3-c860afdb47d4 Duration: 210.20 ms Billed Duration: 211 ms Memory Size: 512 MB Max Memory Used: 171 MB

3 Answers
1

In your first create Challenge Lambda log:

REPORT RequestId: a9efd773-08b6-4b4b-a2b3-d1fb7e3fb502 Duration: 7639.15 ms Billed Duration: 7640 ms

In the documentation of Cognito lambda triggers https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html#important-lambda-considerations

Except for Custom sender Lambda triggers, Amazon Cognito invokes Lambda functions synchronously. When Amazon Cognito calls your Lambda function, it must respond within 5 seconds

As the 7.6 seconds lambda execution is longer than 5s. Cognito side takes it as time out and make an auto-retry.

Java runtime lambda has the most long cold-start time cost. You may search for aws lambda cold start to understand more. There are also many articles talked about how to mitigate that.

profile pictureAWS
Yungang
answered 20 days ago
  • If you see the logs, the 'Init Duration' is not much but what is taking time is the code execution.

    REPORT RequestId: a9efd773-08b6-4b4b-a2b3-d1fb7e3fb502 Duration: 7639.15 ms Billed Duration: 7640 ms Memory Size: 512 MB Max Memory Used: 169 MB Init Duration: 661.01 ms

    My Code for sending email is taking around 9 seconds. 6 seconds jus to initialize SesClient and another 3 seconds to send email:

    try(SesClient sesClient = SesClient.builder().region(Region.AP_SOUTH_1).build()) { logger.log("sending email ..."); SendEmailRequest emailRequest = SendEmailRequest.builder() .source(SENDER_EMAIL) .destination(Destination.builder().toAddresses(userAttributes.get("email").asText()).build()) .message(Message.builder() .subject(Content.builder().data(SUBJECT).build()) .body(Body.builder().text(Content.builder().data(secretCode).build()).build()).build()) .build(); SendEmailResponse sendEmailResponse = sesClient.sendEmail(emailRequest); logger.log("sendEmailResult: " + sendEmailResponse.messageId()); } catch (SesException e) { logger.log("Email sending failed. Error message: " + e.getMessage()); }

    Is there any way to optimize this piece of code or should I move the email part to another lambda which runs in async.

0

Not sure why the second execution is only 210ms

REPORT RequestId: d39e6945-45a2-4f81-a0b3-c860afdb47d4 Duration: 210.20 ms

Is there any way to optimize this piece of code

I am using python lambda with 'smtplib' to send email for createAuthChallenge, never see an issue. I am not using SES, but a SMTP server to deliver email.

should I move the email part to another lambda which runs in async.

Sounds a possible option.

profile pictureAWS
Yungang
answered 20 days ago
0

I got it working to run under 5 seconds by increasing the memory to 2048 MB (which also allocates CPU power linearly) Below are the logs for reference:

`

2024-05-03T14:05:28.408+05:30	INIT_START Runtime Version: java:21.v15 Runtime Version ARN: arn:aws:lambda:ap-south-1::runtime:367cb4c78c9b9b4d4eb04656c9938e85fbed3f853a08f5e0a5f21a46326d3991
2024-05-03T14:05:29.072+05:30	START RequestId: 4343bf41-007c-483b-8f12-3e65a8605a57 Version: $LATEST
2024-05-03T14:05:29.140+05:30	input: {"version":"1","region":"ap-south-1","userPoolId":"XXXXXX","userName":"XXXXXX","callerContext":{"awsSdkVersion":"aws-sdk-java-1.12.641","clientId":"XXXXXX"},"triggerSource":"CreateAuthChallenge_Authentication","request":{"userAttributes":{"sub":"f113dd3a-1021-7084-2495-8c4eb4853463","email_verified":"True","custom:login-path":"XXXXXX","cognito:user_status":"CONFIRMED","name":"XXXXXX","email":"XXXXXX"},"challengeName":"CUSTOM_CHALLENGE","session":[],"userNotFound":false},"response":{"publicChallengeParameters":null,"privateChallengeParameters":null,"challengeMetadata":null}}
2024-05-03T14:05:29.184+05:30	sessionLength: 0
2024-05-03T14:05:29.184+05:30	secretCode: 9184
2024-05-03T14:05:30.696+05:30	sending email ...
2024-05-03T14:05:31.428+05:30	sendEmailResult: 0109018f3d982161-5ca0d668-16e4-4741-a24a-9b82204bef24-000000
2024-05-03T14:05:31.442+05:30	output: {"version":"1","region":"ap-south-1","userPoolId":"XXXXXX","userName":"XXXXXX","callerContext":{"awsSdkVersion":"aws-sdk-java-1.12.641","clientId":"XXXXXX"},"triggerSource":"CreateAuthChallenge_Authentication","request":{"userAttributes":{"sub":"f113dd3a-1021-7084-2495-8c4eb4853463","email_verified":"True","custom:login-path":"XXXXXX","cognito:user_status":"CONFIRMED","name":"XXXXXX","email":"XXXXXX"},"challengeName":"CUSTOM_CHALLENGE","session":[],"userNotFound":false},"response":{"publicChallengeParameters":{"email":"XXXXXX"},"privateChallengeParameters":{"secretLoginCode":"9184"},"challengeMetadata":"9184"}}
2024-05-03T14:05:31.445+05:30	END RequestId: 4343bf41-007c-483b-8f12-3e65a8605a57
2024-05-03T14:05:31.445+05:30	REPORT RequestId: 4343bf41-007c-483b-8f12-3e65a8605a57 Duration: 2372.51 ms Billed Duration: 2373 ms Memory Size: 2048 MB Max Memory Used: 199 MB Init Duration: 662.88 ms

`

NOTE: This however increases the price per 1ms which is $0.0000000333 for 2048 MB.

Shubham
answered 19 days ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions