Managed Services Provider
Amazon Cognito has made it easier than ever to build great apps. All the features in Cognito now let a developer create a great app experience instead of worrying about building, securing and scaling a solution to handle user management, authentication and sync across devices. Before we discuss the use of Cognito for our Ionic app, lets take a look at the AWS Serverless Architecture and see where Cognito fits in.
Why do we want to use Cognito for our Ionic app?
The scope for our project was achieving authentication/authorization, consuming Amazon Cognito services, securing API Gateway and data modelling with DynamoDB(NOSQL) , writing business logic with Lambda microservices. Other Federated identities (FaceBook, Google etc) is out of scope at the moment but can be scaled to in the next iteration.
• Signing up users to Ionic-demo app
• Authenticating/Authorizing users
• Record Observation in Ionic-demo app
• Get All Observations in Ionic-demo app
Here we have a quick visual of Cognito for Authorization
Now that we understand the the architecture for Cognito, let’s get started to accomplish basic authentication using Cognito. This involves Creating User Pools, Creating Federated Identities and the use of AWS Cognito SDK on the client-side for consuming Cognito services.
The work flow for the Authorization looks like this.
Begin by creating User Pools
Create a Federated Identity
Consume Cognito authentication services at the client-side
Role Based Authentication Using Custom Attributes
Create a DynamoDB Database
Create a new API Gateway Services
Consuming AWS SDK Gateway at the Client
Create a custom authorizer in your API
Securing API Gateway Custom Authorization using Cognito User Pool
Let’s go over the work flow in detail now.
Begin by creating User Pools
1. AWS Cognito through AWS Console, select ‘Manage User Pools’
2. Create User Pool
3. Name the User Pool
4. Select Step through settings
5. Choose the attributes for each user in the user pool
6. Set Policies for the password validation
7. Create New App through Apps. Give the App Name you desire and App Client ID is generated for you.
Now your User Pool has been created with its custom settings!
Now create a Federated Identity
1. Head to Cognito Console- ‘Manage Federated Identity’.
2. Name the Identity Pool ID
3. Select Authentication Provider. In our case, it is Cognito.
4. Attach the Federated Identity to User Pool created earlier by entering User Pool ID and App Client ID
5. By default, two roles are created for authorized user of the app and for unauthorized user of the app.
Federated Identity Pool is created and is now attached to the User Pool!
Next step is to consume Cognito authentication services at the client-side
1. Download AWS-SDK, AWS Cognito-SDK and place it in your project library.
2. Change the config settings to accommodate your custom user pool and federated Identity.
Role Based Authentication Using Custom Attributes
Once we have the basic authentication going, the next goal was to achieve role-based authentication. This can be achieved using custom attributes in the User Pool settings.
Steps to create User Pool remain the same. Only now, we will set custom attributes relevant to our application.
Create a DynamoDB Database
Now create a DynamoDB database and then create a Lambda. At this point we need to configure Lambda to the execution role ( IAM )
1. Add resource
2. Add method(GET/POST/PUT/DELETE)
3. Add integration method as Lambda and select the region and the lambda name created earlier.
4. Secure it using IAM role
5. Provide a mapping-template
At this point we can deploy the API after which you will see a URL ready to use for invocation purposes.
Consuming AWS SDK Gateway at the Client
At Client-side, we can invoke this URL using the customized SDK created at the time of API deployment. One can secure the API through IAM role with the following steps.
1. Deploy AWS API gateway on AWS console
2. Generate Custom SDK (API and Lambda) for the desired platform
3. Download the SDK on local machine( I used Javascript as platform)
4. Place the Contents of apiGateway-js-sdk in the client-side/front-end source code.
5. Find the custom apigclient contains methods/functions to invoke the api and the associated lambda function with the request method.
Get a handle to the apigclient in the controller(angularjs) to invoke api.
A few observations with regards to advantage of using IAM role authentication to secure API, is that it is secured through policies on users and resources. The setback would be that it is tightly coupled around AWS ecosystem. Third party cannot make calls to API.
Now we can start Securing API Gateway Custom Authorization using Lambdas
• Download the blueprint for custom authorizer for Amazon Cognito User Pools
• Unzip the file and modify the following variables with your userPoolId and region in the ‘authorizer.js’ file, as follows:
• var userPoolId = ‘{REPLACE_WITH_YOUR_POOL_ID}’;
• var region = ‘{REPLACE_WITH_YOUR_REGION}’;
Zip all the files again, name the .zip file cup_authorizer.zip, and create a Lambda function with that .zip file. Make sure that you only zip the inner files (authorizer.js and node_modules); do not zip the outer directory.
• Choose Node.JS as the Runtime for the Lambda function. For Handler, choose authorizer.handler.
Next, Create a custom authorizer in your API, as shown next.
Now attach the authorizer in Method Request, as shown next.
We can now deploy the API and then we can test the API. If a valid Access Token for your user pool is passed to an API, the API will create a note in a DynamoDB table for that user. Otherwise, the API will throw an unauthorized message back to the application.
In trying to use authorization, we observed that a we have loosely coupled authorization to access end points and that third party can invoke API using valid tokens(provided by cognito) in the header are great features for the user. At the same time one needs to be mindful of the complex custom authorization code.
Securing API Gateway Custom Authorization using Cognito User Pool
Instead of a custom lambda for authorization, we can use custom authorization provided by Cognito User Pools to secure the API. This simplifies the process to a great extent.
At the API Gateway in AWS Console, Select Authorizers and Create ‘Cognito Usr Pool Authorizer’.
This authorizer, intercepts the Restful API calls on methods like GET,POST,DELETE,PUT and checks if the user is from the user pool, the authorized user gets a policy that lets them use the resources. To use Custom Authorizer, Choose the User Pool and Deploy the API and invoke the API using Authorizer header (JWT)
There are some clear advantages to using Custom Authorization
Highly Secured as authorized user is checked against the cognito user pool.
Easy of use as the complexities are encapsulated by Cognito Authorization.
Does not depend on additional Lambda execution.
Combines advantages of earlier 2 methods to achieve authorization.(Cognito + JWT access tokens).
Understanding some of the services of AWS ecosystem was bit like putting together all the pieces of this jigsaw puzzle. Due to lack of information in one place about relatively new service (Cognito) from amazon, resources were few. Much of the information was from the Discussion forums and AWS documentation. Now that it is in one place, hopefully will make some developers’ life easier. Security, in itself is a vast topic and this research was not intended towards touching upon everything but rather use Cognito effectively with other AWS services.