AWS Cognito, Just Another Identity Provider?
Intro
AWS Cognito is an Amazon identity provider service. Similar to Google’s Firebase, you can use the service to allow users to sign up and log in to your application. Cognito saves a lot of time because creating a custom authentication service can be very time-consuming. You will have to compensate for forgotten/reset password flows, session management, and many other security details. I’m going to go over Cognito and help you solve some challenges around custom user authentication. I will start by giving a scenario and then explaining how Cognito and allow you to solve this.
The Scenario
You are working for a client that has 10 applications. The client would like to have a single source for all their users, but each user may have access to 1 or all of their applications. On top of this, there are three user roles. Let’s call them roles A, B, and C. If a user has a role in one application then is given access to another application, they should maintain that same role. So if a user has role B and has access to 4 applications, then if we change them to role A, that role for the user would propagate to all applications they can access.
Cognito Overview
A few Concepts to go over first are:
- AWS Cognito pools
- AWS Cognito user groups
- AWS Cognito custom user attributes.
Cognito user pools are essentially a bucket to put all your users into. If you had many different applications and would want different users across all of them, you would have a single pool for each application. In our scenario, we would want one pool for all our applications. Cognito user groups are ways to group users in a pool. Each group can be given different access permissions to parts of your application or other AWS services. Cognito custom user attributes are custom attributes you can attach to every user in your pool.
Solution
Now back to our challenge of creating a single user pool to access one or many applications while maintaining their roles. I will list them step-by-step and explain.
Step 1:
login to AWS Cognito and create a new user pool.
Step 2:
When creating users, you can assign them to specific user groups. So now, we will create 10 different groups for our 10 different applications. When creating a user, you can assign them to 1 or all groups or applications. You can also update a user in the future when needing them to access other applications.
Step 3:
Now that we have a user pool that can host all your users and 10 different groups representing your 10 different applications, we can add 3 custom attributes to our users. The 3 custom attributes would represent the roles. Roles A, B, and C. When creating a user or modifying an existing user, we can set these role attributes to true or false. Note that currently, custom attributes can only have a type of number or string. Given this restriction, you can choose what makes sense for your scenario. You can get even more creative if you want to have different levels within a role by using a Number type, Allowing different numbers to represent different privilege levels within a role. Privilege levels on user roles would be a very custom implementation that I won’t cover in this post, so please subscribe if you want to get informed in our future post.
Step 4:
Now that we have AWS Cognito all set up, it’s pretty simple to create a login flow allowing or disallowing users to different applications. You can use the below function to authenticate a user. Then check their groups to authorize them vs. the application they are logging into. Finally, you can check their role to grant them certain features within that application.
const authToken = await CognitoConnection.adminInitiateAuth({ password, email })
const userInfo = await CognitoConnection.getUser(authToken)
const userHasRoleA = userInfo['custom:role_a'] === 1
Another Great Feature
Another great thing about user groups is assigning different IAM roles to specific groups, automatically allowing authentication against Lambda functions or other AWS services. Take the scenario that the client has many Lambda functions as microservices for their 10 applications. You can allow or disallow users within groups to be able to access specific microservices. The great thing is this is all baked in. This is all handled under the hood by AWS checking the user’s authentication token so that when they request that specific AWS endpoint, it will check with the user’s group’s IAM role in Cognito. If they are not allowed to access the endpoint, they will automatically get rejected. You got the love AWS.
Conclusion
AWS Cognito is an excellent solution for basic or very custom authentication flows. It allows you to manage access to both your custom application features and your AWS infrastructure all in one place. Thank you for reading, and please do subscribe if you would like to stay up-to-date with all our latest posts.