Passing custom data to AWS createAuthChallenge trigger

Viewed 108

I'm having trouble customizing my Auth Flow with AWS-cognito and AWS-Ses. I would like to do a simple magic link auth, that sends a token by mail whenever a user whats to sign in. My problem is : I need to customize this email before sending it to the users mailbox. I want to have a link that redirects users to my website but they can come from different locations. Let's say, I'm going to redirect some users to https://mysite/foo?<token> and some others to https://mysite/bar?<token>.

But I'm not able to pass custom variables to my AWS cognito auth Triggers.

Right now I have a CUSTOM_AUTH flow, and I use @aws-sdk/client-cognito-identity-provider to initiateAuthCommand. I do not want to use Amplify because all the rest of my app uses the aws SDK.

Here is how I call the initiateAuth command :

import { CognitoIdentityProviderClient, InitiateAuthCommand } from '@aws-sdk/client-cognito-identity-provider'

const poolConfig = {
    accessKeyId: process.env.AWS_APIKEY,
    secretAccessKey: process.env.AWS_SECRETKEY,
    region: process.env.AWS_REGION,
    poolId: process.env.AWS_COGNITO_POOL_ID,
    poolClientId: process.env.AWS_COGNITO_POOL_CLIENT_ID
}

const provider = new CognitoIdentityProviderClient(poolConfig)

const authInput = {
    AuthFlow: "CUSTOM_AUTH",
    AuthParameters : {
        USERNAME: "test@mydomain.com",
    },
    ClientId: process.env.AWS_COGNITO_POOL_CLIENT_ID
}

const signinCommand = new InitiateAuthCommand(authInput)

try {
    const res = await provider.send(signinCommand)
    console.log('Signin success. Result: ', res)
} catch (e) {
    console.log('Signin fail. Error: ', e)
}

and here is my createAuthChallenge trigger :

import { SESv2Client, SendEmailCommand } from "@aws-sdk/client-sesv2";
import { randomDigits } from 'crypto-secure-random-digit';

const config = {
    accessKeyId: process.env.AWS_APIKEY,
    secretAccessKey: process.env.AWS_SECRETKEY,
    region: process.env.AWS_REGION,
}

const client = new SESv2Client(config);

export const handler = async (event) => {

    let secretLoginCode;

    if (!event.request.session || !event.request.session.length) {

        secretLoginCode = randomDigits(10).join('');

        // My problem is here, I can't manage to retrieve here a custom variable, that would be
        // originUrl in this example

        await sendEmail(event.request.userAttributes.email, originUrl, secretLoginCode);

    } else {

        const previousChallenge = event.request.session.slice(-1)[0];
        secretLoginCode = previousChallenge.challengeMetadata.match(/CODE-(\d*)/)[1];
    }

    event.response.publicChallengeParameters = {
        email: event.request.userAttributes.email
    };

    event.response.privateChallengeParameters = { secretLoginCode };

    event.response.challengeMetadata = `CODE-${secretLoginCode}`;

    return event;
};

async function sendEmail(emailAddress, originUrl, secretLoginCode) {

    var params = {
        Destination: {
            ToAddresses: [
                emailAddress
            ]
        },
        Content: {
            Simple: {
                Body: {
                    Html: {
                        Charset: "UTF-8",
                        Data: `<p>Your link to connect is : <a href="${originUrl}/register?t=${secretLoginCode}">here</a></p>`
                    },
                },
                Subject: {
                    Charset: 'UTF-8',
                    Data: 'Test email'
                }
            }

        },
        FromEmailAddress: 'fromAddress@mydomain.com',
    };

    const command = new SendEmailCommand(params);

    await client.send(command);
}

I have tried a lot of things that seems to be documented in AWS docs here :

https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-settings-adaptive-authentication.html#user-pool-settings-adaptive-authentication-accept-user-context-data

It's talking about an EnablePropagateAdditionalUserContextData boolean in my app's client but it looks that this is for a different use case. For device fingerprinting and so. Moreover, it costs extra because you have to enable 'advanced security' and I can't do that as I'm not in charge of the billing. Thus it seems weird to have to pay extra to do something as simple as this.

I have also tried to use ClientMetadata. It should be available in the request to the lambda as this docs shows :

https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-create-auth-challenge.html#aws-lambda-triggers-create-auth-challenge-example

But this doc says that these parameters are not communicated to the createAuthChallenge trigger :

https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html

Why ? Why can't I send custom data to my lambda trigger ? I'm sure I'm missing something but I admit being out of ressource to resolve this. I have tried a lot of things but with no result. It is weird because the need to do this kind of thing must be really common, especially if using a CUSTOM_FLOW_AUTH.

What am I missing ? Does someone around here already had this issue ?

Thanks :)

0 Answers
Related