In my recent blog post “Secure Your App with Cognito”, I discussed about using Cognito User Pools with Cognito Identity Pools to secure a web/mobile application with an API Gateway hosted RESTful backend. There I mentioned about a new feature called built-in UIs which was added to Cognito User Pools recently. The value of this feature further increases with the CUP (Cognito User Pool) support for federated identities. And these two features together make our life even more easy.
CUP built-in UI is a AWS hosted UI with user forms for signin and signup. It’s generated according to the identity provider options we configure on the CUP console. The best hidden feature I like the most is the federated identities also getting added to the users list in CUP. The diagram below shows a logical view of the architecture and the message flow. (Application scenario is same as in the previous article, web/mobile application with a RESTful API)
Let’s go through each step and see what happens
- The user makes the login request on the application and gets redirected to the cognito hosted UI
- The user signs up/signs in using an identity provider available. Here a,b and c denotes the login flows of each identity provider
- On successful login user is re-directed back to the application with the corresponding auth credentials based on the OAuth flow configured (I’m using “Authorization code grant” flow which provides an authorization code)
- The application exchanges the authorization code for tokens with the Token endpoint of the CUP
- Call the API Gateway endpoint including the access token in the request.
- API Gateway custom authorizer authorizes the token with CUP and generates an authorization policy.
- Using the policy generated, secured resources at the backend can now be accessed
Here in step 6 you might be wondering why not use the cognito user pool authorizer instead of the custom authorizer (If you didn’t know already, you can configure a CUP authorizer for API Gateway directly from the aws console). Well, this is mainly due the limitation (might be changed in future) that the CUP authorizer only accepts the id token and checks only whether it’s valid or not. There is no way to handle authorization, which means we cannot control the fine grained access to API endpoints.
So, what approaches can we follow to implement the custom authorizer? Well, this basically has to be decided based on the authorization levels you are planning to have and how you are planning to manage them.
- If it’s a single level with fixed set of scopes, you can use the CUP feature called “Resource servers”. Here you can define an API along with scopes, which you can configure to be included in the token. Scopes can then be read in the custom authorizer and generate the policy accordingly.
- If it’s multiple levels (like different groups of users) you can use the CUP feature called “User Groups”. Here you can define different groups and assign users to them. We can configure this also to be included in the token. Then according to the group we can generate the policy. We can keep a list of policies for each group.
Note that apart from the above approaches there can be various others based on the use case. We even can manage everything at the custom authorizer without using any of the features from CUP.
Finally I must mention you that the cognito user pool is getting better and better at a rapid pace and many features (like built-in UIs, federated identities) were introduced recently. So the decision to use it in your production apps, can be made without any doubts (Well I did 😜)