AWS Amplify + Angular full-stack serverless guide: Part 4
By: Hasitha Kaushan
Tags: Cloudformation, AWS, Serverless, AWS Lambda, Aws Amplify

This is the fourth article of my series on AWS Amplify with Angular full-stack serverless guide. In the previous articles, I explained how to set up an Amplify with Angular project, how to make continuous deployment of that app and how to add social login to the application.

In this article, I will be going off from my pre-planned schedule and I will be bringing up an actual solution that I made for a problem that came up when I was developing a web application using AWS Amplify.

The use case is as follows. In our system, users are added by the admin developers, using the AWS Cognito console. We wanted to add the created users in the user pool to a particular group in Cognito. Of course, this can be done manually instead I wanted to automate the process. The user pool is configured by Amplify CLI.

The solution that I made was to create a custom message lambda triggered in Cognito and within that Lambda function add user to a Cognito user group while customizing the notification email/SMS sent to the user. Amplify CLI generates the necessary Cloudformation stacks assigning particular access policies to particular resources. In this case, CLI generates the IAM policy to Cognito to access the Lambda function. Then comes the actual problem. In our case, we need to access the Cognito resource back from our Lambda function. Even though CLI creates the policies for Cognito to access Lambda function, it doesn’t create vise versa. You still can make a amplify function update to give permission Lambda function to access back Cognito user pool, but it will generate an Error: Cannot add [functionName] due to a cyclic dependency error. Thus, to provide necessary IAM policies to the custom message Lambda function in order to access the Cognito user pool, we can make a custom Cloudformation stack. Let’s get started.

AWS CloudFormation gives you an easy way to model a collection of related AWS and third-party resources, provision them quickly and consistently, and manage them throughout their lifecycles, by treating infrastructure as code. A CloudFormation template describes your desired resources and their dependencies so you can launch and configure them together as a stack. You can use a template to create, update, and delete an entire stack as a single unit, as often as you need to, instead of managing resources individually. You can manage and provision stacks across multiple AWS accounts and AWS Regions.

First, let’s add auth to our project.

amplify add auth

In the process, you need to configure set up a custom message Lambda trigger.

$ Do you want to enable any of the following capabilities?

❯ ◯ Add Google reCaptcha Challenge

◯ Email Verification Link with Redirect

◯ Add User to Group

◯ Email Domain Filtering (deny list)

◯ Email Domain Filtering (allow list)

◯ Custom Auth Challenge Flow (basic scaffolding - not for production)

◯ Override ID Token Claims

Here, you need to enable Email Verification Link with Redirect capability. It will create a custom message Lambda trigger.

Now open amplify/backend/function/<function-name>/src/verification-link.js

Add this code snippet to the Lambda function.

What this code does is, the user is added to the ADMINS group in the Cognito user pool. Obviously, you have to create a group named ADMINS in the user pool in the Cognito console.

The most important part comes up next. We have to create a custom resource that grants the custom message Lambda to access the Cognito user pool. This custom resource depends on the Cognito UserPoolId and the LamdaExecutionRole.

First, you have to modify amplify/backend/backend-config.json

Under amplify/backend we have to make a directory as following.

amplify

\backend

\<custom-category-name>

\<custom-resource-name>

parameters.json

template.json

We need to create the following parameters and assign LambdaExecutionRole an IAM policy that will allow us to access Cognito User Pool based on the UserPoolId. These configurations are made in the template.json file.

Finally, we need to add the above two parameters in parameter.json file with a cloudformation Fn::GetAtt that connect the output of one nested template to our custom template.

One last step, in order to notify CLI about the newly created custom resources, we need to run amplify env checkout <current-env-name> . Then we can make amplify push to deploy our changes to AWS.

This issue worried me for over 12 hours. I hope this one helps anyone out there. Stay safe and happy coding 💛

👋 Join FAUN today and receive similar stories each week in your inbox! ️ Get your weekly dose of the must-read tech stories, news, and tutorials.

Follow us on Twitter 🐦 and Facebook 👥 and Instagram 📷 and join our Facebook and Linkedin Groups 💬