Image for post
Image for post

Magic links with AWS Cognito

Thomas Schoffelen
Jul 26 · 3 min read

I’ve written before about what I consider to be best practices for magic links from a UX perspective. Recently, I got a chance to apply those principles to using magic links with AWS Cognito.

Cognito by is heavily focussed on username and password based login by default. Alongside that it offers ways to do 2-factor authentication and OAuth login, but no direct way of using magic links instead of passwords.

That begs the question: is there a way to work around that? Can we make that workaround simple enough to still retain all the advantages of using Cognito in the first place?

The ingredients

The key in the solution lies in the multi-factor login support Cognito has. This system is built in a flexible manner to not only allow it for use as a second factor, but also as a replacement for a password.

The second important piece of the puzzle is that user accounts in Cognito have attributes. There’s a set of default attributes (email, name, phone, etc.), but you can also add your own custom attributes, and configure those to be editable by the user or only by the admin.

The solution

The combination of those properties of Cognito makes it relatively easy to implement easy to use magic links.

You can find the code for my proof-of-concept on Github. It turned out to be really simple: just a few lambdas (mostly to respond to Cognito’s hooks) and two calls to Cognito via the AWS Amplify library on the front-end.

How it works

How safe is it?

You won’t be able to get access to a user’s account without knowing their email address and having access to their inbox.

Having the authChallenge as a random UUID adds enough entropy to make brute-force attacks unlikely, especially in combination with the login throttling that AWS Cognito has as a built-in feature.

Adding an expiry date to the links (30 minutes in this example) means gaining access to old emails won’t give attackers access to their accounts.

How scalable is this?

This does a AdminUpdateUserAttributes request on every login. That method has a soft limit of 5 calls per second, which should be sufficient for most user bases, as the chance of more than 5 users signing in at the same second is probably very unlikely unless you have 50k+ active users.

If so, you could ask AWS to raise that soft limit, and you should be good for at least another 250k MAUs. After that, it be time to start looking into something more robust to manage your authentication needs :)

How can we further improve UX?

One thing that could be done a more deterministic method for generating authChallenge, so that if the user accidentally sends themselves more than one magic link email in a short period of time, the second send doesn’t make the first link invalid. However, introducing determinism might make the system less safe if done incorrectly.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store