I worked on many login & registration systems in the past 10 years. And one thing I can tell you for sure: It’s somehow always ugly. I even saw many small and big companies alike struggling for multiple years with their authentication solution. I’m not joking: I know multiple companies who worked at least 3 years with a dedicated team only on their login/registration system.

Does it need to be so hard? I mean, back in 2014, it was a different world and there was less open source, fewer standards, no real SaaS providers for authentication.

The gist is: Nowadays this is a solved problem. Please don’t waste your precious time and energy on things like authenticating your users. They are not simple.

Legacy systems running on home-brew authentication

My latest project leads me to introduce AWS Cognito to a very successful German company. It was a migration of a huge 10+ year old PHP application with a homebrew session-based login mechanism, including sticky sessions. At the time of the migration, the system had 12M users, an average of 15k registrations a day with peaks up to 25k and an average of 70k logins a day with peaks up to 100k per day. The session was valid for 30d and would extend the validity of each interaction.

We decided quite early that we would need to split up the monolithic application to scale the organization and teams. Which lead to the introduction of AWS Cognito, so each component could work independently.

I used AWS Cognito before, but always for smaller projects, prototypes and in general for so-called greenfield projects. It became quite the journey.

Would I choose AWS Cognito again? Yes and No. No, if I would be forced to repeat my mistakes and yes if I had my current knowledge.

What is AWS Cognito and why should I care?

Each application needs to handle authentication and authorization. Authentication is the process of proving who you are (like an ID card) and authorization is the process of validating if you are allowed the action - like buying alcohol if you are over the legal age by looking at the birthdate on your ID card.

Or to use very simple words what authentication and authorization are: It’s proofing who you are and validating that you are allowed to do specific actions .

Screenshot of the login from one of the Axel Springer brands

And AWS Cognito is a cheap and easy SaaS (Software-as-a-Service) solution to deliver those features to your applications. It’s based on OAuth2 and OpenId Connect (OIDC) and comes with support for social logins, customization and many more cool features. It also stores your users details and credentials - no need to have your own (insecure) database to store unencrypted user data.

Alternatives

At some point in the lifecycle of any application you will think about how to handle user login and registration in your application. Most modern frameworks like Pythons Django, PHPs Laravel or Javas Spring Framework come with built-in solutions. They will be tightly coupled with your application and the framework you chose, require effort and you will need to run and operate them yourself. Most monolithic applications start this way. It’s still a very valid way if you only have a small application and only a handful of engineers.

If you want a decentralized solution for authentication which is based on open standards, scalable, easy to extend, maintainable and secure, there are three valid alternatives in my opinion:

  1. Use a SaaS solution, like AWS Cognito or direct competitors, most likely Auth0 or Okta (who actually bought Auth0)
  2. Keep using sessions, but push the session into a database and abstract it via a service
  3. Host an OpenId Connect service yourself, most likely Keycloak

For the first option people have some fears, like what happens if my auth-provider is down, people won’t be able to login or register. On the other hand, it’s very easy to use and relieves you of a lot of things - you won’t need to store passwords or even email addresses. It’s the most secure and reliable solution. But money and price is always a consideration - that’s why Auth0 is normally not an option: It is by far the best solution on the market - and by far the most expensive: For the big company I migrated, with 13M users overall, it would cost over 350.000€ a year in fees! Or to be more detailed from my research:

  • 200k monthly active 180k USD/y
  • 400k monthly active 220k USD/y
  • 1M monthly active 350k USD/y

All of these are averaged monthly users paid at the end of the year and it takes into account growth. Other price drivers are higher SLAs or if you want them to use a private cloud for you that’s 45k/y on top.

And that’s already with discounts and an enterprise plan. That’s where AWS Cognito comes in: It is the younger and ugly sibling of a famous Hollywood star.

Screenshot from Auth0, very similar to the AWS Cognito UI

Option two would be using classic sessions and extracting a service to retrieve it. This is in some use cases the best option. If you are building a huge in-house platform it makes sense - it’s the most performant solution. The downside is the needed engineering effort and increase in internal complexity for your application. It makes it harder for external teams to work on your applications, they will need more knowledge and access to other systems.

The third option, which is like running a system similar to AWS Cognito yourself, requires the most engineering effort. Just installing and operating Keycloak , the most common open-source solution, requires quite some work. Try to get this running and scaling in the cloud, don’t forget monitoring! I did it once with EKS and it is quite the work. Don’t get me started talking about customization, you will need to become a Keycloak expert. The only benefit here is the option for the most customization options and operating it yourself if really needed. Imagine you need one login for your platform, which must work with other integrated systems which use strange protocols like CAS instead of Oauth2 or OpenId Connect. Yes, this happens in Germany. And if you integrate other systems with different authentication systems into your application, then something like Keycloak maybe your best option.

Obviously, there are other options, which I would label not valid: Building your own solution or using the functions from a framework. I already did both - it sucks, believe me. With Axel Springer in 2013, we did build everything regarding authentication and authorization ourselves (while partially using libraries and frameworks) and it totally got out of hand. And later we tried to build an OpenId Connect solution based on one of the reference libraries for OpenId Connect - it was better, but we still invested multiple months with a full team in building it. If login and registration are not part of your core offering - don’t do this!

How to use AWS Cognito

It’s actually dead simple: Create a user pool in AWS Cognito, add a client and use in your frontend with the AWS Amplify.js library.

import Amplify from '@aws-amplify/core';

Amplify.configure({
  Auth: {
    mandatorySignIn: true,
    region: 'eu-central-1',
    userPoolId: 'eu-central-1_XXX',
    userPoolWebClientId: 'XXXXXXXXXXXXXXXXXXXXXXXXXX',
    oauth: {
      domain: 'XXXXXXXXXXXXXX.com',
      redirectSignIn: '',
      redirectSignOut: '',
      responseType: 'code',
    },
  },
});

With the Amplify library everything is just one call, be it login, registration, password forgotten, or resend the activation link.

import Auth from '@aws-amplify/auth';

await Auth.signIn({
  username: this.email.toLowerCase(),
  password: this.password,
});

In your backend you just need any JWT library to validate it. For JavaScript/NodeJS you most likely will use json-webtokens and for PHP the library just called jwt . Your backend will need the URL of the JWKS-endpoint from Cognito, where it will find the public key for validating the signature of the JWT. Both backend and frontend will need the user pool id and client id.

If you only want a working solution and don’t care for design: AWS Cognito comes already with all UI masks including error validation and sends pure text emails for double opt-ins via email or if you forgot your password.

Amplify gives your frontend application the ability to connect with AWS Cognito without any effort. You can implement the native user interface forms for authentication, password recovery, account activation. Yes, your clients/frontend will talk directly to AWS Cognito for everything.

Should I use AWS Cognito?

User authentication is a commodity and it’s still hard. It’s also security-relevant and working on it can use quite some time and resources. It’s actually very simple: Using a managed and decentralized service will give you more agility and freedom. You will only realize and understand it afterwards.

There are quite some pitfalls with AWS Cognito you should know about. If you are building a new application and are aware of the pitfalls of AWS Cognito and use it only for authentication and authorization and you don’t store any data within AWS cognition: Yes, definitely. It’s also free for up to 50,000 MAUs (monthly active users).

Do you have a legacy system and do you need a scalable and decentralized login solution? Well, now it depends. AWS Cognito is from the point of engineering and operation costs most likely by far the cheapest option, but it comes with downsides. You can make a lot of errors if you have no experience with the quirks of AWS Cognito.

If you are not careful, using AWS Cognito will feel like implementing your very own auth service

Two things are especially hard: Custom features and migration of existing users. You will need to work with AWS Lambdas functions for both. And you will need to understand how AWS Cognito works under the hood. If you have never worked with serverless technologies before, this can be quite a steep learning curve.

Do you already have more than let’s say 250k monthly active users? Maybe you are already big enough and can think about different solutions.

AWS Cognito is great and ugly at the same time. But with many things in life: Be brave and go for it.