Create a Cognito Identity Pool

Now that we have deployed our backend API; we almost have all the pieces we need for our backend. We have the User Pool that is going to store all of our users and help sign in and sign them up. We also have an S3 bucket that we will use to help our users upload files as attachments for their notes. The final piece that ties all these services together in a secure way is called Amazon Cognito Federated Identities.

Amazon Cognito Federated Identities enables developers to create unique identities for your users and authenticate them with federated identity providers. With a federated identity, you can obtain temporary, limited-privilege AWS credentials to securely access other AWS services such as Amazon DynamoDB, Amazon S3, and Amazon API Gateway.

In this chapter, we are going to create a federated Cognito Identity Pool. We will be using our User Pool as the identity provider. We could also use Facebook, Google, or our own custom identity provider. Once a user is authenticated via our User Pool, the Identity Pool will attach an IAM Role to the user. We will define a policy for this IAM Role to grant access to the S3 bucket and our API. This is the Amazon way of securing your resources.

Let's get started.

Create Pool

From your AWS Console and select Cognito from the list of services.

Select Cognito Service screenshot

Select Manage Federated Identities.

Select Manage Federated Identities Screenshot

Enter an Identity pool name. If you have any existing Identity Pools, you'll need to click the Create new identity pool button.

Fill Cognito Identity Pool Info Screenshot

Select Authentication providers. Under Cognito tab, enter User Pool ID and App Client ID of the User Pool created in the [Create a Cognito user pool]({% link _chapters/create-a-cognito-user-pool.md %}) chapter. Select Create Pool.

Fill Authentication Provider Info Screenshot

Now we need to specify what AWS resources are accessible for users with temporary credentials obtained from the Cognito Identity Pool.

Select View Details. Two Role Summary sections are expanded. The top section summarizes the permission policy for authenticated users, and the bottom section summarizes that for unauthenticated users.

Select View Policy Document in the top section. Then select Edit.

Select Edit Policy Document Screenshot

It will warn you to read the documentation. Select Ok to edit.

Select Confirm Edit Policy Screenshot

Add the following policy into the editor. Replace YOUR_S3_UPLOADS_BUCKET_NAME with the bucket name from the Create an S3 bucket for file uploads chapter. And replace the YOUR_API_GATEWAY_REGION and YOUR_API_GATEWAY_ID with the ones that you get after you deployed your API in the last chapter.

In our case YOUR_S3_UPLOADS_BUCKET_NAME is notes-app-uploads, YOUR_API_GATEWAY_ID is ly55wbovq4, and YOUR_API_GATEWAY_REGION is us-east-1.

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"mobileanalytics:PutEvents",
"cognito-sync:*",
"cognito-identity:*"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::YOUR_S3_UPLOADS_BUCKET_NAME/private/${cognito-identity.amazonaws.com:sub}/*"
]
},
{
"Effect": "Allow",
"Action": [
"execute-api:Invoke"
],
"Resource": [
"arn:aws:execute-api:YOUR_API_GATEWAY_REGION:*:YOUR_API_GATEWAY_ID/*/*/*"
]
}
]
}

A quick note on the block that relates to the S3 Bucket. In the above policy we are granting our logged in users access to the path private/${cognito-identity.amazonaws.com:sub}/. Where cognito-identity.amazonaws.com:sub is the authenticated user's federated identity ID (their user id). So a user has access to only their folder within the bucket. This is how we are securing the uploads for each user.

So in summary we are telling AWS that an authenticated user has access to two resources.

  1. Files in the S3 bucket that are inside a folder with their federated identity id as the name of the folder.
  2. And, the APIs we deployed using API Gateway.

One other thing to note is that the federated identity id is a UUID that is assigned by our Identity Pool. This is the id (event.requestContext.identity.cognitoIdentityId) that we were using as our user id back when we were creating our APIs.

Select Allow.

Submit Cognito Identity Pool Policy Screenshot

Our Cognito Identity Pool should now be created. Let's find out the Identity Pool ID.

Select Dashboard from the left panel, then select Edit identity pool.

Cognito Identity Pool Created Screenshot

Take a note of the Identity pool ID which will be required in the later chapters.

Cognito Identity Pool Created Screenshot

Now before we test our serverless API let's take a quick look at the Cognito User Pool and Cognito Identity Pool and make sure we've got a good idea of the two concepts and the differences between them.

TODO: Add a link to an automated creation with terraform or cloudformation.

Cognito User Pool vs Identity Pool

We often get questions about the differences between the Cognito User Pool and the Identity Pool, so it is worth covering in detail. The two can seem a bit similar in function and it is not entirely clear what they are for. Let's first start with the official definitions.

Here is what AWS defines the Cognito User Pool as:

Amazon Cognito User Pool makes it easy for developers to add sign-up and sign-in functionality to web and mobile applications. It serves as your own identity provider to maintain a user directory. It supports user registration and sign-in, as well as provisioning identity tokens for signed-in users.

And the Cognito Federated Identities or Identity Pool is defined as:

Amazon Cognito Federated Identities enables developers to create unique identities for your users and authenticate them with federated identity providers. With a federated identity, you can obtain temporary, limited-privilege AWS credentials to securely access other AWS services such as Amazon DynamoDB, Amazon S3, and Amazon API Gateway.

Unfortunately they are both a bit vague and confusingly similar. Here is a more practical description of what they are.

User Pool

Say you were creating a new web or mobile app and you were thinking about how to handle user registration, authentication, and account recovery. This is where Cognito User Pools would come in. Cognito User Pool handles all of this and as a developer you just need to use the SDK to retrieve user related information.

Identity Pool

Cognito Identity Pool (or Cognito Federated Identities) on the other hand is a way to authorize your users to use the various AWS services. Say you wanted to allow a user to have access to your S3 bucket so that they could upload a file; you could specify that while creating an Identity Pool. And to create these levels of access, the Identity Pool has its own concept of an identity (or user). The source of these identities (or users) could be a Cognito User Pool or even Facebook or Google.

User Pool vs Identity Pool

To clarify this a bit more, let's put these two services in context of each other. Here is how they play together.

Amazon Cognito User Pool vs Identity Pool screenshot

Notice how we could use the User Pool, social networks, or even our own custom authentication system as the identity provider for the Cognito Identity Pool. The Cognito Identity Pool simply takes all your identity providers and puts them together (federates them). And with all of this it can now give your users secure access to your AWS services, regardless of where they come from.

So in summary; the Cognito User Pool stores all your users which then plugs into your Cognito Identity Pool which can give your users access to your AWS services.

Now that we have a good understanding of how our users will be handled, let's finish up our backend by testing our APIs.