Amazon Cognito Identity Provider examples using SDK for JavaScript (v3) - AWS SDK Code Examples

There are more AWS SDK examples available in the AWS Doc SDK Examples GitHub repo.

Amazon Cognito Identity Provider examples using SDK for JavaScript (v3)

The following code examples show you how to perform actions and implement common scenarios by using the AWS SDK for JavaScript (v3) with Amazon Cognito Identity Provider.

Actions are code excerpts from larger programs and must be run in context. While actions show you how to call individual service functions, you can see actions in context in their related scenarios.

Scenarios are code examples that show you how to accomplish specific tasks by calling multiple functions within a service or combined with other AWS services.

Each example includes a link to the complete source code, where you can find instructions on how to set up and run the code in context.

Get started

The following code examples show how to get started using Amazon Cognito.

SDK for JavaScript (v3)
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

import { paginateListUserPools, CognitoIdentityProviderClient, } from "@aws-sdk/client-cognito-identity-provider"; const client = new CognitoIdentityProviderClient({}); export const helloCognito = async () => { const paginator = paginateListUserPools({ client }, {}); const userPoolNames = []; for await (const page of paginator) { const names = page.UserPools.map((pool) => pool.Name); userPoolNames.push(...names); } console.log("User pool names: "); console.log(userPoolNames.join("\n")); return userPoolNames; };
  • For API details, see ListUserPools in AWS SDK for JavaScript API Reference.

Actions

The following code example shows how to use AdminGetUser.

SDK for JavaScript (v3)
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

const adminGetUser = ({ userPoolId, username }) => { const client = new CognitoIdentityProviderClient({}); const command = new AdminGetUserCommand({ UserPoolId: userPoolId, Username: username, }); return client.send(command); };
  • For API details, see AdminGetUser in AWS SDK for JavaScript API Reference.

The following code example shows how to use AdminInitiateAuth.

SDK for JavaScript (v3)
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

const adminInitiateAuth = ({ clientId, userPoolId, username, password }) => { const client = new CognitoIdentityProviderClient({}); const command = new AdminInitiateAuthCommand({ ClientId: clientId, UserPoolId: userPoolId, AuthFlow: AuthFlowType.ADMIN_USER_PASSWORD_AUTH, AuthParameters: { USERNAME: username, PASSWORD: password }, }); return client.send(command); };

The following code example shows how to use AdminRespondToAuthChallenge.

SDK for JavaScript (v3)
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

const adminRespondToAuthChallenge = ({ userPoolId, clientId, username, totp, session, }) => { const client = new CognitoIdentityProviderClient({}); const command = new AdminRespondToAuthChallengeCommand({ ChallengeName: ChallengeNameType.SOFTWARE_TOKEN_MFA, ChallengeResponses: { SOFTWARE_TOKEN_MFA_CODE: totp, USERNAME: username, }, ClientId: clientId, UserPoolId: userPoolId, Session: session, }); return client.send(command); };

The following code example shows how to use AssociateSoftwareToken.

SDK for JavaScript (v3)
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

const associateSoftwareToken = (session) => { const client = new CognitoIdentityProviderClient({}); const command = new AssociateSoftwareTokenCommand({ Session: session, }); return client.send(command); };

The following code example shows how to use ConfirmDevice.

SDK for JavaScript (v3)
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

const confirmDevice = ({ deviceKey, accessToken, passwordVerifier, salt }) => { const client = new CognitoIdentityProviderClient({}); const command = new ConfirmDeviceCommand({ DeviceKey: deviceKey, AccessToken: accessToken, DeviceSecretVerifierConfig: { PasswordVerifier: passwordVerifier, Salt: salt, }, }); return client.send(command); };
  • For API details, see ConfirmDevice in AWS SDK for JavaScript API Reference.

The following code example shows how to use ConfirmSignUp.

SDK for JavaScript (v3)
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

const confirmSignUp = ({ clientId, username, code }) => { const client = new CognitoIdentityProviderClient({}); const command = new ConfirmSignUpCommand({ ClientId: clientId, Username: username, ConfirmationCode: code, }); return client.send(command); };
  • For API details, see ConfirmSignUp in AWS SDK for JavaScript API Reference.

The following code example shows how to use DeleteUser.

SDK for JavaScript (v3)
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

/** * Delete the signed-in user. Useful for allowing a user to delete their * own profile. * @param {{ region: string, accessToken: string }} config * @returns {Promise<[import("@aws-sdk/client-cognito-identity-provider").DeleteUserCommandOutput | null, unknown]>} */ export const deleteUser = async ({ region, accessToken }) => { try { const client = new CognitoIdentityProviderClient({ region }); const response = await client.send( new DeleteUserCommand({ AccessToken: accessToken }), ); return [response, null]; } catch (err) { return [null, err]; } };
  • For API details, see DeleteUser in AWS SDK for JavaScript API Reference.

The following code example shows how to use InitiateAuth.

SDK for JavaScript (v3)
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

const initiateAuth = ({ username, password, clientId }) => { const client = new CognitoIdentityProviderClient({}); const command = new InitiateAuthCommand({ AuthFlow: AuthFlowType.USER_PASSWORD_AUTH, AuthParameters: { USERNAME: username, PASSWORD: password, }, ClientId: clientId, }); return client.send(command); };
  • For API details, see InitiateAuth in AWS SDK for JavaScript API Reference.

The following code example shows how to use ListUsers.

SDK for JavaScript (v3)
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

const listUsers = ({ userPoolId }) => { const client = new CognitoIdentityProviderClient({}); const command = new ListUsersCommand({ UserPoolId: userPoolId, }); return client.send(command); };
  • For API details, see ListUsers in AWS SDK for JavaScript API Reference.

The following code example shows how to use ResendConfirmationCode.

SDK for JavaScript (v3)
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

const resendConfirmationCode = ({ clientId, username }) => { const client = new CognitoIdentityProviderClient({}); const command = new ResendConfirmationCodeCommand({ ClientId: clientId, Username: username, }); return client.send(command); };

The following code example shows how to use RespondToAuthChallenge.

SDK for JavaScript (v3)
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

const respondToAuthChallenge = ({ clientId, username, session, userPoolId, code, }) => { const client = new CognitoIdentityProviderClient({}); const command = new RespondToAuthChallengeCommand({ ChallengeName: ChallengeNameType.SOFTWARE_TOKEN_MFA, ChallengeResponses: { SOFTWARE_TOKEN_MFA_CODE: code, USERNAME: username, }, ClientId: clientId, UserPoolId: userPoolId, Session: session, }); return client.send(command); };

The following code example shows how to use SignUp.

SDK for JavaScript (v3)
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

const signUp = ({ clientId, username, password, email }) => { const client = new CognitoIdentityProviderClient({}); const command = new SignUpCommand({ ClientId: clientId, Username: username, Password: password, UserAttributes: [{ Name: "email", Value: email }], }); return client.send(command); };
  • For API details, see SignUp in AWS SDK for JavaScript API Reference.

The following code example shows how to use UpdateUserPool.

SDK for JavaScript (v3)
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

/** * Connect a Lambda function to the PreSignUp trigger for a Cognito user pool * @param {{ region: string, userPoolId: string, handlerArn: string }} config * @returns {Promise<[import("@aws-sdk/client-cognito-identity-provider").UpdateUserPoolCommandOutput | null, unknown]>} */ export const addPreSignUpHandler = async ({ region, userPoolId, handlerArn, }) => { try { const cognitoClient = new CognitoIdentityProviderClient({ region, }); const command = new UpdateUserPoolCommand({ UserPoolId: userPoolId, LambdaConfig: { PreSignUp: handlerArn, }, }); const response = await cognitoClient.send(command); return [response, null]; } catch (err) { return [null, err]; } };
  • For API details, see UpdateUserPool in AWS SDK for JavaScript API Reference.

The following code example shows how to use VerifySoftwareToken.

SDK for JavaScript (v3)
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

const verifySoftwareToken = (totp) => { const client = new CognitoIdentityProviderClient({}); // The 'Session' is provided in the response to 'AssociateSoftwareToken'. const session = process.env.SESSION; if (!session) { throw new Error( "Missing a valid Session. Did you run 'admin-initiate-auth'?", ); } const command = new VerifySoftwareTokenCommand({ Session: session, UserCode: totp, }); return client.send(command); };

Scenarios

The following code example shows how to automatically confirm known Amazon Cognito users with a Lambda function.

  • Configure a user pool to call a Lambda function for the PreSignUp trigger.

  • Sign up a user with Amazon Cognito.

  • The Lambda function scans a DynamoDB table and automatically confirms known users.

  • Sign in as the new user, then clean up resources.

SDK for JavaScript (v3)
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

Configure an interactive "Scenario" run. The JavaScript (v3) examples share a Scenario runner to streamline complex examples. The complete source code is on GitHub.

import { AutoConfirm } from "./scenario-auto-confirm.js"; /** * The context is passed to every scenario. Scenario steps * will modify the context. */ const context = { errors: [], users: [ { UserName: "test_user_1", UserEmail: "test_email_1@example.com", }, { UserName: "test_user_2", UserEmail: "test_email_2@example.com", }, { UserName: "test_user_3", UserEmail: "test_email_3@example.com", }, ], }; /** * Three Scenarios are created for the workflow. A Scenario is an orchestration class * that simplifies running a series of steps. */ export const scenarios = { // Demonstrate automatically confirming known users in a database. "auto-confirm": AutoConfirm(context), }; // Call function if run directly import { fileURLToPath } from "node:url"; import { parseScenarioArgs } from "@aws-doc-sdk-examples/lib/scenario/index.js"; if (process.argv[1] === fileURLToPath(import.meta.url)) { parseScenarioArgs(scenarios, { name: "Cognito user pools and triggers", description: "Demonstrate how to use the AWS SDKs to customize Amazon Cognito authentication behavior.", }); }

This Scenario demonstrates auto-confirming a known user. It orchestrates the example steps.

import { wait } from "@aws-doc-sdk-examples/lib/utils/util-timers.js"; import { Scenario, ScenarioAction, ScenarioInput, ScenarioOutput, } from "@aws-doc-sdk-examples/lib/scenario/scenario.js"; import { getStackOutputs, logCleanUpReminder, promptForStackName, promptForStackRegion, skipWhenErrors, } from "./steps-common.js"; import { populateTable } from "./actions/dynamodb-actions.js"; import { addPreSignUpHandler, deleteUser, getUser, signIn, signUpUser, } from "./actions/cognito-actions.js"; import { getLatestLogStreamForLambda, getLogEvents, } from "./actions/cloudwatch-logs-actions.js"; /** * @typedef {{ * errors: Error[], * password: string, * users: { UserName: string, UserEmail: string }[], * selectedUser?: string, * stackName?: string, * stackRegion?: string, * token?: string, * confirmDeleteSignedInUser?: boolean, * TableName?: string, * UserPoolClientId?: string, * UserPoolId?: string, * UserPoolArn?: string, * AutoConfirmHandlerArn?: string, * AutoConfirmHandlerName?: string * }} State */ const greeting = new ScenarioOutput( "greeting", (/** @type {State} */ state) => `This demo will populate some users into the \ database created as part of the "${state.stackName}" stack. \ Then the autoConfirmHandler will be linked to the PreSignUp \ trigger from Cognito. Finally, you will choose a user to sign up.`, { skipWhen: skipWhenErrors }, ); const logPopulatingUsers = new ScenarioOutput( "logPopulatingUsers", "Populating the DynamoDB table with some users.", { skipWhenErrors: skipWhenErrors }, ); const logPopulatingUsersComplete = new ScenarioOutput( "logPopulatingUsersComplete", "Done populating users.", { skipWhen: skipWhenErrors }, ); const populateUsers = new ScenarioAction( "populateUsers", async (/** @type {State} */ state) => { const [_, err] = await populateTable({ region: state.stackRegion, tableName: state.TableName, items: state.users, }); if (err) { state.errors.push(err); } }, { skipWhen: skipWhenErrors, }, ); const logSetupSignUpTrigger = new ScenarioOutput( "logSetupSignUpTrigger", "Setting up the PreSignUp trigger for the Cognito User Pool.", { skipWhen: skipWhenErrors }, ); const setupSignUpTrigger = new ScenarioAction( "setupSignUpTrigger", async (/** @type {State} */ state) => { const [_, err] = await addPreSignUpHandler({ region: state.stackRegion, userPoolId: state.UserPoolId, handlerArn: state.AutoConfirmHandlerArn, }); if (err) { state.errors.push(err); } }, { skipWhen: skipWhenErrors, }, ); const logSetupSignUpTriggerComplete = new ScenarioOutput( "logSetupSignUpTriggerComplete", ( /** @type {State} */ state, ) => `The lambda function "${state.AutoConfirmHandlerName}" \ has been configured as the PreSignUp trigger handler for the user pool "${state.UserPoolId}".`, { skipWhen: skipWhenErrors }, ); const selectUser = new ScenarioInput( "selectedUser", "Select a user to sign up.", { type: "select", choices: (/** @type {State} */ state) => state.users.map((u) => u.UserName), skipWhen: skipWhenErrors, default: (/** @type {State} */ state) => state.users[0].UserName, }, ); const checkIfUserAlreadyExists = new ScenarioAction( "checkIfUserAlreadyExists", async (/** @type {State} */ state) => { const [user, err] = await getUser({ region: state.stackRegion, userPoolId: state.UserPoolId, username: state.selectedUser, }); if (err?.name === "UserNotFoundException") { // Do nothing. We're not expecting the user to exist before // sign up is complete. return; } if (err) { state.errors.push(err); return; } if (user) { state.errors.push( new Error( `The user "${state.selectedUser}" already exists in the user pool "${state.UserPoolId}".`, ), ); } }, { skipWhen: skipWhenErrors, }, ); const createPassword = new ScenarioInput( "password", "Enter a password that has at least eight characters, uppercase, lowercase, numbers and symbols.", { type: "password", skipWhen: skipWhenErrors, default: "Abcd1234!" }, ); const logSignUpExistingUser = new ScenarioOutput( "logSignUpExistingUser", (/** @type {State} */ state) => `Signing up user "${state.selectedUser}".`, { skipWhen: skipWhenErrors }, ); const signUpExistingUser = new ScenarioAction( "signUpExistingUser", async (/** @type {State} */ state) => { const signUp = (password) => signUpUser({ region: state.stackRegion, userPoolClientId: state.UserPoolClientId, username: state.selectedUser, email: state.users.find((u) => u.UserName === state.selectedUser) .UserEmail, password, }); let [_, err] = await signUp(state.password); while (err?.name === "InvalidPasswordException") { console.warn("The password you entered was invalid."); await createPassword.handle(state); [_, err] = await signUp(state.password); } if (err) { state.errors.push(err); } }, { skipWhen: skipWhenErrors }, ); const logSignUpExistingUserComplete = new ScenarioOutput( "logSignUpExistingUserComplete", (/** @type {State} */ state) => `"${state.selectedUser} was signed up successfully.`, { skipWhen: skipWhenErrors }, ); const logLambdaLogs = new ScenarioAction( "logLambdaLogs", async (/** @type {State} */ state) => { console.log( "Waiting a few seconds to let Lambda write to CloudWatch Logs...\n", ); await wait(10); const [logStream, logStreamErr] = await getLatestLogStreamForLambda({ functionName: state.AutoConfirmHandlerName, region: state.stackRegion, }); if (logStreamErr) { state.errors.push(logStreamErr); return; } console.log( `Getting some recent events from log stream "${logStream.logStreamName}"`, ); const [logEvents, logEventsErr] = await getLogEvents({ functionName: state.AutoConfirmHandlerName, region: state.stackRegion, eventCount: 10, logStreamName: logStream.logStreamName, }); if (logEventsErr) { state.errors.push(logEventsErr); return; } console.log(logEvents.map((ev) => `\t${ev.message}`).join("")); }, { skipWhen: skipWhenErrors }, ); const logSignInUser = new ScenarioOutput( "logSignInUser", (/** @type {State} */ state) => `Let's sign in as ${state.selectedUser}`, { skipWhen: skipWhenErrors }, ); const signInUser = new ScenarioAction( "signInUser", async (/** @type {State} */ state) => { const [response, err] = await signIn({ region: state.stackRegion, clientId: state.UserPoolClientId, username: state.selectedUser, password: state.password, }); if (err?.name === "PasswordResetRequiredException") { state.errors.push(new Error("Please reset your password.")); return; } if (err) { state.errors.push(err); return; } state.token = response?.AuthenticationResult?.AccessToken; }, { skipWhen: skipWhenErrors }, ); const logSignInUserComplete = new ScenarioOutput( "logSignInUserComplete", (/** @type {State} */ state) => `Successfully signed in. Your access token starts with: ${state.token.slice(0, 11)}`, { skipWhen: skipWhenErrors }, ); const confirmDeleteSignedInUser = new ScenarioInput( "confirmDeleteSignedInUser", "Do you want to delete the currently signed in user?", { type: "confirm", skipWhen: skipWhenErrors }, ); const deleteSignedInUser = new ScenarioAction( "deleteSignedInUser", async (/** @type {State} */ state) => { const [_, err] = await deleteUser({ region: state.stackRegion, accessToken: state.token, }); if (err) { state.errors.push(err); } }, { skipWhen: (/** @type {State} */ state) => skipWhenErrors(state) || !state.confirmDeleteSignedInUser, }, ); const logErrors = new ScenarioOutput( "logErrors", (/** @type {State}*/ state) => { const errorList = state.errors .map((err) => ` - ${err.name}: ${err.message}`) .join("\n"); return `Scenario errors found:\n${errorList}`; }, { // Don't log errors when there aren't any! skipWhen: (/** @type {State} */ state) => state.errors.length === 0, }, ); export const AutoConfirm = (context) => new Scenario( "AutoConfirm", [ promptForStackName, promptForStackRegion, getStackOutputs, greeting, logPopulatingUsers, populateUsers, logPopulatingUsersComplete, logSetupSignUpTrigger, setupSignUpTrigger, logSetupSignUpTriggerComplete, selectUser, checkIfUserAlreadyExists, createPassword, logSignUpExistingUser, signUpExistingUser, logSignUpExistingUserComplete, logLambdaLogs, logSignInUser, signInUser, logSignInUserComplete, confirmDeleteSignedInUser, deleteSignedInUser, logCleanUpReminder, logErrors, ], context, );

These are steps that are shared with other Scenarios.

import { ScenarioAction, ScenarioInput, ScenarioOutput, } from "@aws-doc-sdk-examples/lib/scenario/scenario.js"; import { getCfnOutputs } from "@aws-doc-sdk-examples/lib/sdk/cfn-outputs.js"; export const skipWhenErrors = (state) => state.errors.length > 0; export const getStackOutputs = new ScenarioAction( "getStackOutputs", async (state) => { if (!state.stackName || !state.stackRegion) { state.errors.push( new Error( "No stack name or region provided. The stack name and \ region are required to fetch CFN outputs relevant to this example.", ), ); return; } const outputs = await getCfnOutputs(state.stackName, state.stackRegion); Object.assign(state, outputs); }, ); export const promptForStackName = new ScenarioInput( "stackName", "Enter the name of the stack you deployed earlier.", { type: "input", default: "PoolsAndTriggersStack" }, ); export const promptForStackRegion = new ScenarioInput( "stackRegion", "Enter the region of the stack you deployed earlier.", { type: "input", default: "us-east-1" }, ); export const logCleanUpReminder = new ScenarioOutput( "logCleanUpReminder", "All done. Remember to run 'cdk destroy' to teardown the stack.", { skipWhen: skipWhenErrors }, );

A handler for the PreSignUp trigger with a Lambda function.

import type { PreSignUpTriggerEvent, Handler } from "aws-lambda"; import type { UserRepository } from "./user-repository"; import { DynamoDBUserRepository } from "./user-repository"; export class PreSignUpHandler { private userRepository: UserRepository; constructor(userRepository: UserRepository) { this.userRepository = userRepository; } private isPreSignUpTriggerSource(event: PreSignUpTriggerEvent): boolean { return event.triggerSource === "PreSignUp_SignUp"; } private getEventUserEmail(event: PreSignUpTriggerEvent): string { return event.request.userAttributes.email; } async handlePreSignUpTriggerEvent( event: PreSignUpTriggerEvent, ): Promise<PreSignUpTriggerEvent> { console.log( `Received presignup from ${event.triggerSource} for user '${event.userName}'`, ); if (!this.isPreSignUpTriggerSource(event)) { return event; } const eventEmail = this.getEventUserEmail(event); console.log(`Looking up email ${eventEmail}.`); const storedUserInfo = await this.userRepository.getUserInfoByEmail(eventEmail); if (!storedUserInfo) { console.log( `Email ${eventEmail} not found. Email verification is required.`, ); return event; } if (storedUserInfo.UserName !== event.userName) { console.log( `UserEmail ${eventEmail} found, but stored UserName '${storedUserInfo.UserName}' does not match supplied UserName '${event.userName}'. Verification is required.`, ); } else { console.log( `UserEmail ${eventEmail} found with matching UserName ${storedUserInfo.UserName}. User is confirmed.`, ); event.response.autoConfirmUser = true; event.response.autoVerifyEmail = true; } return event; } } const createPreSignUpHandler = (): PreSignUpHandler => { const tableName = process.env.TABLE_NAME; if (!tableName) { throw new Error("TABLE_NAME environment variable is not set"); } const userRepository = new DynamoDBUserRepository(tableName); return new PreSignUpHandler(userRepository); }; export const handler: Handler = async (event: PreSignUpTriggerEvent) => { const preSignUpHandler = createPreSignUpHandler(); return preSignUpHandler.handlePreSignUpTriggerEvent(event); };

Module of CloudWatch Logs actions.

import { CloudWatchLogsClient, GetLogEventsCommand, OrderBy, paginateDescribeLogStreams, } from "@aws-sdk/client-cloudwatch-logs"; /** * Get the latest log stream for a Lambda function. * @param {{ functionName: string, region: string }} config * @returns {Promise<[import("@aws-sdk/client-cloudwatch-logs").LogStream | null, unknown]>} */ export const getLatestLogStreamForLambda = async ({ functionName, region }) => { try { const logGroupName = `/aws/lambda/${functionName}`; const cwlClient = new CloudWatchLogsClient({ region }); const paginator = paginateDescribeLogStreams( { client: cwlClient }, { descending: true, limit: 1, orderBy: OrderBy.LastEventTime, logGroupName, }, ); for await (const page of paginator) { return [page.logStreams[0], null]; } } catch (err) { return [null, err]; } }; /** * Get the log events for a Lambda function's log stream. * @param {{ * functionName: string, * logStreamName: string, * eventCount: number, * region: string * }} config * @returns {Promise<[import("@aws-sdk/client-cloudwatch-logs").OutputLogEvent[] | null, unknown]>} */ export const getLogEvents = async ({ functionName, logStreamName, eventCount, region, }) => { try { const cwlClient = new CloudWatchLogsClient({ region }); const logGroupName = `/aws/lambda/${functionName}`; const response = await cwlClient.send( new GetLogEventsCommand({ logStreamName: logStreamName, limit: eventCount, logGroupName: logGroupName, }), ); return [response.events, null]; } catch (err) { return [null, err]; } };

Module of Amazon Cognito actions.

import { AdminGetUserCommand, CognitoIdentityProviderClient, DeleteUserCommand, InitiateAuthCommand, SignUpCommand, UpdateUserPoolCommand, } from "@aws-sdk/client-cognito-identity-provider"; /** * Connect a Lambda function to the PreSignUp trigger for a Cognito user pool * @param {{ region: string, userPoolId: string, handlerArn: string }} config * @returns {Promise<[import("@aws-sdk/client-cognito-identity-provider").UpdateUserPoolCommandOutput | null, unknown]>} */ export const addPreSignUpHandler = async ({ region, userPoolId, handlerArn, }) => { try { const cognitoClient = new CognitoIdentityProviderClient({ region, }); const command = new UpdateUserPoolCommand({ UserPoolId: userPoolId, LambdaConfig: { PreSignUp: handlerArn, }, }); const response = await cognitoClient.send(command); return [response, null]; } catch (err) { return [null, err]; } }; /** * Attempt to register a user to a user pool with a given username and password. * @param {{ * region: string, * userPoolClientId: string, * username: string, * email: string, * password: string * }} config * @returns {Promise<[import("@aws-sdk/client-cognito-identity-provider").SignUpCommandOutput | null, unknown]>} */ export const signUpUser = async ({ region, userPoolClientId, username, email, password, }) => { try { const cognitoClient = new CognitoIdentityProviderClient({ region, }); const response = await cognitoClient.send( new SignUpCommand({ ClientId: userPoolClientId, Username: username, Password: password, UserAttributes: [{ Name: "email", Value: email }], }), ); return [response, null]; } catch (err) { return [null, err]; } }; /** * Sign in a user to Amazon Cognito using a username and password authentication flow. * @param {{ region: string, clientId: string, username: string, password: string }} config * @returns {Promise<[import("@aws-sdk/client-cognito-identity-provider").InitiateAuthCommandOutput | null, unknown]>} */ export const signIn = async ({ region, clientId, username, password }) => { try { const cognitoClient = new CognitoIdentityProviderClient({ region }); const response = await cognitoClient.send( new InitiateAuthCommand({ AuthFlow: "USER_PASSWORD_AUTH", ClientId: clientId, AuthParameters: { USERNAME: username, PASSWORD: password }, }), ); return [response, null]; } catch (err) { return [null, err]; } }; /** * Retrieve an existing user from a user pool. * @param {{ region: string, userPoolId: string, username: string }} config * @returns {Promise<[import("@aws-sdk/client-cognito-identity-provider").AdminGetUserCommandOutput | null, unknown]>} */ export const getUser = async ({ region, userPoolId, username }) => { try { const cognitoClient = new CognitoIdentityProviderClient({ region }); const response = await cognitoClient.send( new AdminGetUserCommand({ UserPoolId: userPoolId, Username: username, }), ); return [response, null]; } catch (err) { return [null, err]; } }; /** * Delete the signed-in user. Useful for allowing a user to delete their * own profile. * @param {{ region: string, accessToken: string }} config * @returns {Promise<[import("@aws-sdk/client-cognito-identity-provider").DeleteUserCommandOutput | null, unknown]>} */ export const deleteUser = async ({ region, accessToken }) => { try { const client = new CognitoIdentityProviderClient({ region }); const response = await client.send( new DeleteUserCommand({ AccessToken: accessToken }), ); return [response, null]; } catch (err) { return [null, err]; } };

Module of DynamoDB actions.

import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; import { BatchWriteCommand, DynamoDBDocumentClient, } from "@aws-sdk/lib-dynamodb"; /** * Populate a DynamoDB table with provide items. * @param {{ region: string, tableName: string, items: Record<string, unknown>[] }} config * @returns {Promise<[import("@aws-sdk/lib-dynamodb").BatchWriteCommandOutput | null, unknown]>} */ export const populateTable = async ({ region, tableName, items }) => { try { const ddbClient = new DynamoDBClient({ region }); const docClient = DynamoDBDocumentClient.from(ddbClient); const response = await docClient.send( new BatchWriteCommand({ RequestItems: { [tableName]: items.map((item) => ({ PutRequest: { Item: item, }, })), }, }), ); return [response, null]; } catch (err) { return [null, err]; } };

The following code example shows how to:

  • Sign up and confirm a user with a username, password, and email address.

  • Set up multi-factor authentication by associating an MFA application with the user.

  • Sign in by using a password and an MFA code.

SDK for JavaScript (v3)
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

For the best experience, clone the GitHub repository and run this example. The following code represents a sample of the full example application.

import { logger } from "@aws-doc-sdk-examples/lib/utils/util-log.js"; import { signUp } from "../../../actions/sign-up.js"; import { FILE_USER_POOLS } from "./constants.js"; import { getSecondValuesFromEntries } from "@aws-doc-sdk-examples/lib/utils/util-csv.js"; const validateClient = (clientId) => { if (!clientId) { throw new Error( `App client id is missing. Did you run 'create-user-pool'?`, ); } }; const validateUser = (username, password, email) => { if (!(username && password && email)) { throw new Error( `Username, password, and email must be provided as arguments to the 'sign-up' command.`, ); } }; const signUpHandler = async (commands) => { const [_, username, password, email] = commands; try { validateUser(username, password, email); /** * @type {string[]} */ const values = getSecondValuesFromEntries(FILE_USER_POOLS); const clientId = values[0]; validateClient(clientId); logger.log("Signing up."); await signUp({ clientId, username, password, email }); logger.log(`Signed up. A confirmation email has been sent to: ${email}.`); logger.log( `Run 'confirm-sign-up ${username} <code>' to confirm your account.`, ); } catch (err) { logger.error(err); } }; export { signUpHandler }; const signUp = ({ clientId, username, password, email }) => { const client = new CognitoIdentityProviderClient({}); const command = new SignUpCommand({ ClientId: clientId, Username: username, Password: password, UserAttributes: [{ Name: "email", Value: email }], }); return client.send(command); }; import { logger } from "@aws-doc-sdk-examples/lib/utils/util-log.js"; import { confirmSignUp } from "../../../actions/confirm-sign-up.js"; import { FILE_USER_POOLS } from "./constants.js"; import { getSecondValuesFromEntries } from "@aws-doc-sdk-examples/lib/utils/util-csv.js"; const validateClient = (clientId) => { if (!clientId) { throw new Error( `App client id is missing. Did you run 'create-user-pool'?`, ); } }; const validateUser = (username) => { if (!username) { throw new Error( `Username name is missing. It must be provided as an argument to the 'confirm-sign-up' command.`, ); } }; const validateCode = (code) => { if (!code) { throw new Error( `Verification code is missing. It must be provided as an argument to the 'confirm-sign-up' command.`, ); } }; const confirmSignUpHandler = async (commands) => { const [_, username, code] = commands; try { validateUser(username); validateCode(code); /** * @type {string[]} */ const values = getSecondValuesFromEntries(FILE_USER_POOLS); const clientId = values[0]; validateClient(clientId); logger.log("Confirming user."); await confirmSignUp({ clientId, username, code }); logger.log( `User confirmed. Run 'admin-initiate-auth ${username} <password>' to sign in.`, ); } catch (err) { logger.error(err); } }; export { confirmSignUpHandler }; const confirmSignUp = ({ clientId, username, code }) => { const client = new CognitoIdentityProviderClient({}); const command = new ConfirmSignUpCommand({ ClientId: clientId, Username: username, ConfirmationCode: code, }); return client.send(command); }; import qrcode from "qrcode-terminal"; import { logger } from "@aws-doc-sdk-examples/lib/utils/util-log.js"; import { adminInitiateAuth } from "../../../actions/admin-initiate-auth.js"; import { associateSoftwareToken } from "../../../actions/associate-software-token.js"; import { FILE_USER_POOLS } from "./constants.js"; import { getFirstEntry } from "@aws-doc-sdk-examples/lib/utils/util-csv.js"; const handleMfaSetup = async (session, username) => { const { SecretCode, Session } = await associateSoftwareToken(session); // Store the Session for use with 'VerifySoftwareToken'. process.env.SESSION = Session; console.log( "Scan this code in your preferred authenticator app, then run 'verify-software-token' to finish the setup.", ); qrcode.generate( `otpauth://totp/${username}?secret=${SecretCode}`, { small: true }, console.log, ); }; const handleSoftwareTokenMfa = (session) => { // Store the Session for use with 'AdminRespondToAuthChallenge'. process.env.SESSION = session; }; const validateClient = (id) => { if (!id) { throw new Error( `User pool client id is missing. Did you run 'create-user-pool'?`, ); } }; const validateId = (id) => { if (!id) { throw new Error(`User pool id is missing. Did you run 'create-user-pool'?`); } }; const validateUser = (username, password) => { if (!(username && password)) { throw new Error( `Username and password must be provided as arguments to the 'admin-initiate-auth' command.`, ); } }; const adminInitiateAuthHandler = async (commands) => { const [_, username, password] = commands; try { validateUser(username, password); const [userPoolId, clientId] = getFirstEntry(FILE_USER_POOLS); validateId(userPoolId); validateClient(clientId); logger.log("Signing in."); const { ChallengeName, Session } = await adminInitiateAuth({ clientId, userPoolId, username, password, }); if (ChallengeName === "MFA_SETUP") { logger.log("MFA setup is required."); return handleMfaSetup(Session, username); } if (ChallengeName === "SOFTWARE_TOKEN_MFA") { handleSoftwareTokenMfa(Session); logger.log(`Run 'admin-respond-to-auth-challenge ${username} <totp>'`); } } catch (err) { logger.error(err); } }; export { adminInitiateAuthHandler }; const adminInitiateAuth = ({ clientId, userPoolId, username, password }) => { const client = new CognitoIdentityProviderClient({}); const command = new AdminInitiateAuthCommand({ ClientId: clientId, UserPoolId: userPoolId, AuthFlow: AuthFlowType.ADMIN_USER_PASSWORD_AUTH, AuthParameters: { USERNAME: username, PASSWORD: password }, }); return client.send(command); }; import { logger } from "@aws-doc-sdk-examples/lib/utils/util-log.js"; import { adminRespondToAuthChallenge } from "../../../actions/admin-respond-to-auth-challenge.js"; import { getFirstEntry } from "@aws-doc-sdk-examples/lib/utils/util-csv.js"; import { FILE_USER_POOLS } from "./constants.js"; const verifyUsername = (username) => { if (!username) { throw new Error( `Username is missing. It must be provided as an argument to the 'admin-respond-to-auth-challenge' command.`, ); } }; const verifyTotp = (totp) => { if (!totp) { throw new Error( `Time-based one-time password (TOTP) is missing. It must be provided as an argument to the 'admin-respond-to-auth-challenge' command.`, ); } }; const storeAccessToken = (token) => { process.env.AccessToken = token; }; const adminRespondToAuthChallengeHandler = async (commands) => { const [_, username, totp] = commands; try { verifyUsername(username); verifyTotp(totp); const [userPoolId, clientId] = getFirstEntry(FILE_USER_POOLS); const session = process.env.SESSION; const { AuthenticationResult } = await adminRespondToAuthChallenge({ clientId, userPoolId, username, totp, session, }); storeAccessToken(AuthenticationResult.AccessToken); logger.log("Successfully authenticated."); } catch (err) { logger.error(err); } }; export { adminRespondToAuthChallengeHandler }; const respondToAuthChallenge = ({ clientId, username, session, userPoolId, code, }) => { const client = new CognitoIdentityProviderClient({}); const command = new RespondToAuthChallengeCommand({ ChallengeName: ChallengeNameType.SOFTWARE_TOKEN_MFA, ChallengeResponses: { SOFTWARE_TOKEN_MFA_CODE: code, USERNAME: username, }, ClientId: clientId, UserPoolId: userPoolId, Session: session, }); return client.send(command); }; import { logger } from "@aws-doc-sdk-examples/lib/utils/util-log.js"; import { verifySoftwareToken } from "../../../actions/verify-software-token.js"; const validateTotp = (totp) => { if (!totp) { throw new Error( `Time-based one-time password (TOTP) must be provided to the 'validate-software-token' command.`, ); } }; const verifySoftwareTokenHandler = async (commands) => { const [_, totp] = commands; try { validateTotp(totp); logger.log("Verifying TOTP."); await verifySoftwareToken(totp); logger.log("TOTP Verified. Run 'admin-initiate-auth' again to sign-in."); } catch (err) { logger.error(err); } }; export { verifySoftwareTokenHandler }; const verifySoftwareToken = (totp) => { const client = new CognitoIdentityProviderClient({}); // The 'Session' is provided in the response to 'AssociateSoftwareToken'. const session = process.env.SESSION; if (!session) { throw new Error( "Missing a valid Session. Did you run 'admin-initiate-auth'?", ); } const command = new VerifySoftwareTokenCommand({ Session: session, UserCode: totp, }); return client.send(command); };