Created
June 27, 2025 02:51
-
-
Save SevanBadal/7810766efd197d428d06d0fd990ef111 to your computer and use it in GitHub Desktop.
AWS Amplify Gen 2: REST API Lambda Function for Creating Cognito Users
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // amplify/backend.ts | |
| import { defineBackend } from "@aws-amplify/backend"; | |
| import { auth } from "./auth/resource"; | |
| import { data } from "./data/resource"; | |
| import { PolicyStatement, Effect } from "aws-cdk-lib/aws-iam"; | |
| import { | |
| RestApi, | |
| LambdaIntegration, | |
| AuthorizationType, | |
| CognitoUserPoolsAuthorizer, | |
| } from "aws-cdk-lib/aws-apigateway"; | |
| import { createUser } from "./functions/create-user/resource"; | |
| import { Stack } from "aws-cdk-lib"; | |
| const backend = defineBackend({ | |
| auth, | |
| data, | |
| createUser, | |
| }); | |
| // Create REST API Stack for user management | |
| const apiStack = backend.createStack("UserManagementAPI"); | |
| // Create the REST API | |
| const userApi = new RestApi(apiStack, "UserManagementRestApi", { | |
| restApiName: "UserManagementAPI", | |
| deployOptions: { | |
| stageName: "prod", | |
| }, | |
| defaultCorsPreflightOptions: { | |
| allowOrigins: ["*"], | |
| allowMethods: ["POST"], | |
| allowHeaders: ["Content-Type", "Authorization"], | |
| }, | |
| }); | |
| // Create Cognito authorizer using the auth resource | |
| const cognitoAuthorizer = new CognitoUserPoolsAuthorizer( | |
| apiStack, | |
| "UserApiAuthorizer", | |
| { | |
| cognitoUserPools: [backend.auth.resources.userPool], | |
| } | |
| ); | |
| // Add the /users/create endpoint | |
| const usersResource = userApi.root.addResource("users"); | |
| const createResource = usersResource.addResource("create"); | |
| // Add POST method with Lambda integration | |
| createResource.addMethod( | |
| "POST", | |
| new LambdaIntegration(backend.createUser.resources.lambda), | |
| { | |
| authorizationType: AuthorizationType.COGNITO, | |
| authorizer: cognitoAuthorizer, | |
| } | |
| ); | |
| // Grant Lambda permission to create users in Cognito | |
| backend.createUser.resources.lambda.addToRolePolicy( | |
| new PolicyStatement({ | |
| effect: Effect.ALLOW, | |
| actions: [ | |
| "cognito-idp:AdminCreateUser", // you only cognito-idp:AdminCreateUser for this example | |
| "cognito-idp:AdminGetUser", | |
| "cognito-idp:AdminSetUserPassword", | |
| ], | |
| resources: [backend.auth.resources.userPool.userPoolArn], | |
| }) | |
| ); | |
| backend.createUser.addEnvironment( | |
| "AMPLIFY_AUTH_USERPOOL_ID", | |
| backend.auth.resources.userPool.userPoolId | |
| ); | |
| // Add the API URL to outputs | |
| backend.addOutput({ | |
| custom: { | |
| UserManagementAPI: userApi.url, | |
| API: { | |
| [userApi.restApiName]: { | |
| endpoint: userApi.url, | |
| region: Stack.of(userApi).region, | |
| apiName: userApi.restApiName, | |
| }, | |
| }, | |
| }, | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // amplify/functions/create-user/handler.ts | |
| import { APIGatewayProxyHandler } from "aws-lambda"; | |
| import { | |
| CognitoIdentityProviderClient, | |
| AdminCreateUserCommand, | |
| } from "@aws-sdk/client-cognito-identity-provider"; | |
| const env = process.env; | |
| const cognito = new CognitoIdentityProviderClient(); | |
| export const handler: APIGatewayProxyHandler = async (event) => { | |
| // Enable CORS | |
| const headers = { | |
| "Access-Control-Allow-Origin": "*", | |
| "Access-Control-Allow-Headers": "Content-Type,Authorization", | |
| "Content-Type": "application/json", | |
| }; | |
| // Handle preflight requests | |
| // if (event.httpMethod === "OPTIONS") { | |
| // return { | |
| // statusCode: 200, | |
| // headers, | |
| // body: "", | |
| // }; | |
| // } | |
| try { | |
| // Check if user is authenticated (Amplify adds this to the event if the token is valid) | |
| if (!event.requestContext.authorizer?.claims) { | |
| return { | |
| statusCode: 401, | |
| headers, | |
| body: JSON.stringify({ message: "Unauthorized" }), | |
| }; | |
| } | |
| // Parse request body | |
| const { email, firstName, lastName, temporaryPassword } = JSON.parse( | |
| event.body || "{}" | |
| ); | |
| // Validate input | |
| if (!email || !firstName || !lastName || !temporaryPassword) { | |
| return { | |
| statusCode: 400, | |
| headers, | |
| body: JSON.stringify({ message: "All fields are required" }), | |
| }; | |
| } | |
| if (temporaryPassword.length < 8) { | |
| return { | |
| statusCode: 400, | |
| headers, | |
| body: JSON.stringify({ | |
| message: "Password must be at least 8 characters long", | |
| }), | |
| }; | |
| } | |
| // Use the User Pool ID from Amplify environment | |
| const userPoolId = env.AMPLIFY_AUTH_USERPOOL_ID; | |
| const command = new AdminCreateUserCommand({ | |
| UserPoolId: userPoolId, | |
| Username: email, | |
| UserAttributes: [ | |
| { | |
| Name: "email", | |
| Value: email, | |
| }, | |
| { | |
| Name: "given_name", | |
| Value: firstName, | |
| }, | |
| { | |
| Name: "family_name", | |
| Value: lastName, | |
| }, | |
| { | |
| Name: "email_verified", | |
| Value: "true", | |
| }, | |
| ], | |
| TemporaryPassword: temporaryPassword, | |
| MessageAction: "SUPPRESS", // Remove to send welcome email | |
| DesiredDeliveryMediums: ["EMAIL"], | |
| }); | |
| const result = await cognito.send(command); | |
| return { | |
| statusCode: 201, | |
| headers, | |
| body: JSON.stringify({ | |
| message: "User created successfully", | |
| user: { | |
| username: result.User?.Username, | |
| email: email, | |
| status: result.User?.UserStatus, | |
| }, | |
| }), | |
| }; | |
| } catch (error: any) { | |
| console.error("Error creating user:", error); | |
| // Handle specific Cognito errors | |
| if (error.code === "UsernameExistsException") { | |
| return { | |
| statusCode: 409, | |
| headers, | |
| body: JSON.stringify({ | |
| message: "A user with this email already exists", | |
| }), | |
| }; | |
| } | |
| if (error.code === "InvalidPasswordException") { | |
| return { | |
| statusCode: 400, | |
| headers, | |
| body: JSON.stringify({ | |
| message: "Password does not meet requirements", | |
| }), | |
| }; | |
| } | |
| return { | |
| statusCode: 500, | |
| headers, | |
| body: JSON.stringify({ message: "Failed to create user" }), | |
| }; | |
| } | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // amplify/functions/create-user/resource.ts | |
| import { defineFunction } from "@aws-amplify/backend"; | |
| export const createUser = defineFunction({ | |
| name: "create-user", | |
| entry: "./handler.ts", | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment