In Gorilla Labs, we are always looking to research new tools and share that knowledge with our colleagues. Currently, we are developing an app to show all the events that Gorilla Logic schedules. The app will allow users to see events, add them to an “attending” list, get to them using a maps app, and add reminders for them to their personal calendar. Since the app involves users and permissions, there needs to be a way to manage these users — allow them to log in, give them authorization, and restrict permissions. Nowadays, in the Cloud computing era, there are several Cloud services for managing user authentication and authorization. For our app, we chose to use AWS Cognito, which is part of a set of Amazon services called AWS Mobile Hub. Amazon Cognito is a Cloud tool used mostly for granting access to the AWS Cloud. This blog post will provide a brief explanation of AWS Cognito, how we integrated it with the iOS and Android platforms, the case we developed for this post, and the roadblocks we encountered.
What is AWS Cognito?
Amazon Cognito is a user authentication service that offers simple and secure user sign-up, sign-in, and access control. It provides a good amount of features such as a managed user directory, the ability to sign in with an existing provider (known as “federation”), a hosted UI or SDK for integrating multiple programming languages, SAML/Google/Facebook as providers, AWS credentials, and access control. Here is a diagram showing the flow for social providers:
AWS Cognito offers numerous possibilities for integrating with AWS. However, depending on the use case you need to develop, it could be easy to confuse these integrations. The AWS integration possibilities are essentially made up of Cognito User Pools and Cognito Identity Pools. In the next section, we are going to describe these concepts to make them easier to differentiate.
For this app, we need to manage a user directory — in this case, Gorilla Logic employees — for the first phase of the project. This requires allowing users to log in through a Google corporate email account matching the gorillalogic.com domain.
Cognito User Pools
Cognito User Pools exist to authenticate users for the applications that developers make. Say you create a new web or mobile app and you are thinking about how to handle user registration, authentication, and account recovery. This is where Cognito User Pools comes in, saving developers the hassle of creating user authentication from scratch like we used to. The only thing you need to integrate is an AWS Cognito User Pool to manage user sign-up, sign-in and password policies. AWS Cognito complies with SAML/OpenID standards, among other well-known services such as Google/Facebook authentication, simplifying and integrating in just one solution for several providers. A Cognito User Pool is essentially another authentication provider just like Facebook or Twitter.
Cognito Identity Pools
This is a feature designed to allow different users to have access to AWS Services through Cognito User Pools or social logins (Google, Facebook, SAML, OpenID and Custom) under the AWS Account used. You can map users to different roles and permissions and get temporary AWS credentials for accessing AWS services such as Amazon S3, Amazon DynamoDB, Amazon API Gateway, and AWS Lambda. If 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 a Cognito Identity Pool (or “Federated Identity,” as it is also called). To create these levels of access, the Identity Pool has its own concept of an “identity” or “user.” The source of these identities could be a Cognito User Pool or even Facebook or Google. So, to recap:
• AWS Cognito User Pools manage a user directory for an application (through both a user pool and third-party providers).
• AWS Cognito Federated Identities grant access to Amazon Services.
Since we want to allow users to log in to the app just by using a Google account, we initially tried to link an Identity Pool to Google (making a Google app in the Google Developers Console beforehand, of course) just to give temporary access to the app and AWS resources. However, this approach didn’t work mainly for two reasons.
1. There is no easy way to perform a pre-authorization task when the user performs a login through a third-party provider (Google in this case). The only way would be to develop a custom identity pool from scratch, but that would involve extra work that Amazon Cognito might already have the ability to do for us. Another option could be to use a chain of providers. This option is currently under research to see if it fits for our use case.
2. Thinking of a second phase to open the app to other users (with the right separation of roles or groups), we can’t limit the login to Google or Facebook without having our own user pool as well. This way, we can register users that use other email services.
The other approach consists in having a Cognito User Pool with a social provider configured to allow users to log in to the app with a third party social provider — in our case, Google. In the event we need other providers, we can expand to incorporate other social providers such as Facebook or Twitter. This strategy offers an advantage because the configuration of the pre-authorization task through a lambda function is simpler than making a custom identity pool to configure the login restriction. The login can be performed with the help of the AWS Cognito SDK for iOS (Swift and Objective-C).
During our research, we encountered a lot of roadblocks that showed us there were features and situations where Amazon Cognito wasn’t as refined as we would have wished. Some of these points won’t be significant due to the fact that our case was so specific, but it is still good to mention them for future reference.
1. We decided to configure an Identity Pool with the use of the AWS Cognito SDK for both platforms (Android and iOS), making use of the AWSAuthUI library. This library came with a user interface that seemed to meet all the expectations in terms of functionality; however, when we had to modify the UI, it wasn’t an easy job. Due to the fact that this package comes closed, the best practice is to keep it intact and not make any changes to its UI. It offers only a very limited set of properties that can be modified, such as the screen logo, background color (only solid colors are permitted), and certain buttons, among others. You can’t use an animation for the logo, but only a static PNG image. To achieve matching designs for the login page, we needed to get rid of AWSAuthUI and make the sign-up screen from scratch, which increased the development time considerably on both platforms.
2. We had to abandon the idea of using the Identity Pool configuration because we couldn’t find a way to configure a pre-authorization trigger just by using a lambda function.
3. The documentation is poorly written when guiding the user through the configuration steps, using different words to link to the same pages or sections, which can often lead to misunderstandings.
4. When we decided to go with the Cognito User Pool Approach by configuring Google Accounts as a third party social provider, we found some limitations regarding the SDK on both platforms:
a. iOS: AWS Cognito SDK seems to be poorly updated; one of the failures was that the SDK didn’t perform very well when the user needed to do an OAuth procedure using Google. AWS Cognito offers a Hosted Web UI allowing for a “Log in using Google” button to be shown. At the time of our research, this Hosted Web UI was shown using a SFSafariViewController; however, Apple recommends using ASWebAuthenticationSession, which is a class that manages sharing a one-time login between a Safari instance and an app. Currently, there are some issues logged in Github, some of which are waiting for an update to be fixed. Also, it’s very important to mention that a Hosted Web UI doesn’t offer the best user experience in native development; having this button in the SDK as a feature would be very useful in these cases.
b. Android: When using Amazon Cognito User Pools, the minimum API level for Android is API 23. However, when using just a social provider (such as Facebook or Google), the minimum API level is 19. If there is a requirement change, a good portion of market share could be lost just by adding the use of Cognito User Pools to an app allowing social provider login. The AWS Cognito SDK for Android is not compatible yet with the new Androidx package convention, something that suggests the SDK is not updated often enough. Android Pie, for example, was released in early August, and all the apps using the AWS Cognito SDK on this platform could potentially have some issues because Android Pie removed some Apache dependencies in its system, meaning that every app now has to add these dependencies to the source code.
As we see, there is no perfect, plug-and-play framework to apply to a use case. There is still a fair amount work ahead of us to get Amazon Cognito perfectly calibrated for our app, but we’ve certainly gotten off to a good start!