Skip to content

Commit 3fc4799

Browse files
authored
JavaScript (v3): Cognito - Add the "auto-confirm user" scenario. Part of the Pools and Triggers workflow. (#7056)
1 parent c49f896 commit 3fc4799

34 files changed

+1836
-6
lines changed

.doc_gen/metadata/cognito-identity-provider_metadata.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,14 @@ cognito-identity-provider_DeleteUser:
753753
snippet_tags:
754754
- gov2.cognito-identity-provider.CognitoActions.struct
755755
- gov2.cognito-identity-provider.DeleteUser
756+
JavaScript:
757+
versions:
758+
- sdk_version: 3
759+
github: javascriptv3/example_code/cross-services/wkflw-pools-triggers
760+
excerpts:
761+
- description:
762+
snippet_tags:
763+
- javascript.v3.cognito-idp.actions.DeleteUser
756764
services:
757765
cognito-identity-provider: {DeleteUser}
758766
cognito-identity-provider_CreateUserPool:
@@ -793,6 +801,15 @@ cognito-identity-provider_UpdateUserPool:
793801
snippet_tags:
794802
- gov2.cognito-identity-provider.CognitoActions.struct
795803
- gov2.cognito-identity-provider.UpdateUserPool
804+
JavaScript:
805+
versions:
806+
- sdk_version: 3
807+
github: javascriptv3/example_code/cross-services/wkflw-pools-triggers
808+
sdkguide:
809+
excerpts:
810+
- description:
811+
snippet_tags:
812+
- javascript.v3.cognito-idp.actions.UpdateUserPool
796813
services:
797814
cognito-identity-provider: {UpdateUserPool}
798815
cognito-identity-provider_ForgotPassword:

.doc_gen/metadata/cross_metadata.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,38 @@ cross_CognitoAutoConfirmUser:
822822
- description: Clean up resources.
823823
snippet_tags:
824824
- gov2.cognito-identity-provider.Resources.complete
825+
JavaScript:
826+
versions:
827+
- sdk_version: 3
828+
github: javascriptv3/example_code/cross-services/wkflw-pools-triggers
829+
sdk_guide:
830+
excerpts:
831+
- description: |
832+
Configure an interactive "Scenario" run. The JavaScript (v3) examples
833+
share a Scenario runner to streamline complex examples. The complete
834+
source code is on GitHub.
835+
snippet_tags:
836+
- javascript.v3.wkflw.pools-triggers.index
837+
- description: |
838+
This Scenario demonstrates auto-confirming a known user.
839+
It orchestrates the example steps.
840+
snippet_tags:
841+
- javascript.v3.wkflw.pools-triggers.AutoConfirm
842+
- description: These are steps that are shared with other Scenarios.
843+
snippet_tags:
844+
- javascript.v3.wkflw.pools-triggers.common
845+
- description: A handler for the <code>PreSignUp</code> trigger with a &LAM; function.
846+
snippet_tags:
847+
- javascript.v3.wkflw.pools-triggers.handler.AutoConfirm
848+
- description: Module of &CWL; actions.
849+
snippet_files:
850+
- javascriptv3/example_code/cross-services/wkflw-pools-triggers/actions/cloudwatch-logs-actions.js
851+
- description: Module of &COG; actions.
852+
snippet_files:
853+
- javascriptv3/example_code/cross-services/wkflw-pools-triggers/actions/cognito-actions.js
854+
- description: Module of &DDB; actions.
855+
snippet_files:
856+
- javascriptv3/example_code/cross-services/wkflw-pools-triggers/actions/dynamodb-actions.js
825857
services:
826858
cognito-identity-provider: {UpdateUserPool, SignUp, InitiateAuth, DeleteUser}
827859
lambda: {}

javascriptv3/biome.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
"./example_code/kinesis/kinesis-cdk",
1414
"./example_code/medical-imaging/scenarios/health-image-sets/pixel-data-verification/openjphjs/openjphjs.js",
1515
"./example_code/cross-services/textract-react",
16-
"**/dist"
16+
"**/dist",
17+
"**/cdk.out",
18+
"cdk.json"
1719
]
1820
},
1921
"formatter": {

javascriptv3/example_code/cognito-identity-provider/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,21 @@ Code excerpts that show you how to call individual service functions.
4444
- [AssociateSoftwareToken](actions/associate-software-token.js#L9)
4545
- [ConfirmDevice](actions/confirm-device.js#L9)
4646
- [ConfirmSignUp](actions/confirm-sign-up.js#L9)
47+
- [DeleteUser](../cross-services/wkflw-pools-triggers/actions/cognito-actions.js#L122)
4748
- [InitiateAuth](actions/initiate-auth.js#L10)
4849
- [ListUsers](actions/list-users.js#L9)
4950
- [ResendConfirmationCode](actions/resend-confirmation-code.js#L9)
5051
- [RespondToAuthChallenge](actions/respond-to-auth-challenge.js#L10)
5152
- [SignUp](actions/sign-up.js#L9)
53+
- [UpdateUserPool](../cross-services/wkflw-pools-triggers/actions/cognito-actions.js#L13)
5254
- [VerifySoftwareToken](actions/verify-software-token.js#L9)
5355

5456
### Scenarios
5557

5658
Code examples that show you how to accomplish a specific task by calling multiple
5759
functions within the same service.
5860

61+
- [Automatically confirm known users with a Lambda function](../cross-services/wkflw-pools-triggers/index.js)
5962
- [Sign up a user with a user pool that requires MFA](actions/admin-initiate-auth.js)
6063

6164

@@ -104,6 +107,22 @@ node ./hello.js
104107
```
105108

106109

110+
#### Automatically confirm known users with a Lambda function
111+
112+
This example shows you how to automatically confirm known Amazon Cognito users with a Lambda function.
113+
114+
- Configure a user pool to call a Lambda function for the <code>PreSignUp</code> trigger.
115+
- Sign up a user with Amazon Cognito.
116+
- The Lambda function scans a DynamoDB table and automatically confirms known users.
117+
- Sign in as the new user, then clean up resources.
118+
119+
<!--custom.scenario_prereqs.cross_CognitoAutoConfirmUser.start-->
120+
<!--custom.scenario_prereqs.cross_CognitoAutoConfirmUser.end-->
121+
122+
123+
<!--custom.scenarios.cross_CognitoAutoConfirmUser.start-->
124+
<!--custom.scenarios.cross_CognitoAutoConfirmUser.end-->
125+
107126
#### Sign up a user with a user pool that requires MFA
108127

109128
This example shows you how to do the following:
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# Customize Amazon Cognito authentication behavior with Lambda functions
2+
3+
## Overview
4+
5+
This example shows how to use AWS SDKs to customize Amazon Cognito authentication behavior. You can configure
6+
your Amazon Cognito user pool to automatically invoke AWS Lambda functions at various points in the authentication
7+
process, such as before sign-up, during sign-in, and after authentication.
8+
9+
There are three workflows demonstrated by this example:
10+
11+
* Automatically confirm and verify the email of known users by using a pre sign-up trigger.
12+
* [Not yet implemented] Automatically add known users at sign-in by using a migrate user trigger.
13+
* [Not yet implemented] Write custom information to an Amazon DynamoDB table after users are authenticated by using a post authentication trigger.
14+
15+
These workflows are described in more detail in the main [README](../../../../workflows/user_pools_and_lambda_triggers/README.md)
16+
for these examples.
17+
18+
## Automatically confirm known users
19+
20+
A [pre sign-up Lambda trigger](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-pre-sign-up.html)
21+
is invoked when a user starts the sign-up process and lets your Lambda function
22+
take action before Amazon Cognito adds the user to the user pool.
23+
24+
## Automatically migrate known users
25+
26+
A [migrate user Lambda trigger](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-migrate-user.html)
27+
is invoked when a user doesn't exist in the user pool at sign-in with a password.
28+
After the Lambda function returns successfully, Amazon Cognito creates the user in the user pool.
29+
30+
## Write custom activity after authentication
31+
32+
A [post authentication Lambda trigger](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-post-authentication.html)
33+
is invoked after signing in a user, so you can add custom logic after Amazon Cognito authenticates the user.
34+
35+
## ⚠ Important
36+
37+
* Running this code might result in charges to your AWS account.
38+
* Running the tests might result in charges to your AWS account.
39+
* We recommend that you grant your code least privilege. At most, grant only the minimum permissions required to perform the task. For more information, see [Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege).
40+
* This code is not tested in every AWS Region. For more information, see [AWS Regional Services](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services).
41+
42+
## Run the examples
43+
44+
### Prerequisites
45+
46+
For general prerequisites, see the [README](../../../README.md#prerequisites) in the `javascriptv3` folder.
47+
48+
### Setup
49+
50+
This example deploys several resources by using an AWS CloudFormation stack. This stack
51+
deploys the following resources:
52+
53+
* An Amazon DynamoDB table named `doc-example-custom-users` that has a `UserEmail` primary key.
54+
This table functions as an external user store.
55+
* An Amazon Cognito user pool that requires an email, sends an email with verification code
56+
when a new user is added, does not require MFA, and allows account recovery with a verified email.
57+
* An Amazon Cognito client application. This is required for client calls to sign-up and
58+
authentication users.
59+
* An AWS Identity and Access Management (IAM) role that can be assumed by Lambda.
60+
This role grants permission to Lambda to read from and write to the DynamoDB table and
61+
write to CloudWatch Logs.
62+
63+
### Deploy AWS resources
64+
65+
The AWS resources for this example are deployed by using the AWS Cloud Development Kit (AWS CDK).
66+
67+
To install the AWS CDK, follow the instructions in the
68+
[Developer Guide](https://docs.aws.amazon.com/cdk/v2/guide/home.html).
69+
70+
Deploy resources at a command prompt from the [cdk](./cdk/) folder:
71+
72+
```
73+
npm install
74+
cdk deploy
75+
```
76+
77+
### Instructions
78+
79+
Run `./index --help` for instructions on running a scenario.
80+
81+
### Cleanup
82+
83+
Delete resources deployed for this example by deleting the stack.
84+
85+
Delete the stack at a command prompt from the [cdk](./cdk/) folder:
86+
87+
```
88+
cdk destroy
89+
```
90+
91+
## Additional resources
92+
93+
- [Amazon Cognito Identity Provider Developer Guide](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html)
94+
- [Amazon Cognito Identity Provider API Reference](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/Welcome.html)
95+
- [SDK for JavaScript V3 Amazon Cognito Identity Provider reference](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/cognito-identity-provider/)
96+
97+
---
98+
99+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: Apache-2.0
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import {
5+
CloudWatchLogsClient,
6+
GetLogEventsCommand,
7+
OrderBy,
8+
paginateDescribeLogStreams,
9+
} from "@aws-sdk/client-cloudwatch-logs";
10+
11+
/**
12+
* Get the latest log stream for a Lambda function.
13+
* @param {{ functionName: string, region: string }} config
14+
* @returns {Promise<[import("@aws-sdk/client-cloudwatch-logs").LogStream | null, unknown]>}
15+
*/
16+
export const getLatestLogStreamForLambda = async ({ functionName, region }) => {
17+
try {
18+
const logGroupName = `/aws/lambda/${functionName}`;
19+
const cwlClient = new CloudWatchLogsClient({ region });
20+
const paginator = paginateDescribeLogStreams(
21+
{ client: cwlClient },
22+
{
23+
descending: true,
24+
limit: 1,
25+
orderBy: OrderBy.LastEventTime,
26+
logGroupName,
27+
},
28+
);
29+
30+
for await (const page of paginator) {
31+
return [page.logStreams[0], null];
32+
}
33+
} catch (err) {
34+
return [null, err];
35+
}
36+
};
37+
38+
/**
39+
* Get the log events for a Lambda function's log stream.
40+
* @param {{
41+
* functionName: string,
42+
* logStreamName: string,
43+
* eventCount: number,
44+
* region: string
45+
* }} config
46+
* @returns {Promise<[import("@aws-sdk/client-cloudwatch-logs").OutputLogEvent[] | null, unknown]>}
47+
*/
48+
export const getLogEvents = async ({
49+
functionName,
50+
logStreamName,
51+
eventCount,
52+
region,
53+
}) => {
54+
try {
55+
const cwlClient = new CloudWatchLogsClient({ region });
56+
const logGroupName = `/aws/lambda/${functionName}`;
57+
const response = await cwlClient.send(
58+
new GetLogEventsCommand({
59+
logStreamName: logStreamName,
60+
limit: eventCount,
61+
logGroupName: logGroupName,
62+
}),
63+
);
64+
65+
return [response.events, null];
66+
} catch (err) {
67+
return [null, err];
68+
}
69+
};

0 commit comments

Comments
 (0)