Implementing passwordless sign-in flow with email in Cognito

We can configure Cognito to send email verification codes to users via Amazon Simple Email Service.

1. Problem statement

Alice’s passwordless authentication project continues! Her manager and the business owner are excited about the positive feedback received from users on the new sign-in method via SMS. It’s no surprise that stakeholders have decided to introduce a new passwordless authentication option to the application.

Alice needs to configure the Cognito user pool to send verification codes to application users via email. After some research, she decides to set up Amazon Simple Email Service (SES) as the medium for sending emails to users.

This post is Part 2 of the Passwordless Authentication Options with Cognito series.

2. Pre-requisites

This post will not cover how to create the following:

  • A Cognito user pool with hosted UI/managed login, Cognito domain, and callback URL.
  • An app client.
  • Route 53 records.

It also barely touches how to set up SES for sending emails.

Links to the relevant documentation pages will be provided at the end of the post for those who need them.

3. Passwordless authentication with email

Let’s see how we can set up SES to send verification codes to the users’ email addresses.

3.1. Set up the SES account

First, we need to set up the SES account if it hasn’t been done yet. Since this article isn’t focused on SES, I won’t delve into the details of the service. Instead, I’ll provide some links at the bottom of this page that refer to the relevant parts of the documentation.

In brief, we need access to an email address that we can verify. This address will appear in the FROM field of the authentication code emails that users receive. Optionally, we can choose a custom domain instead of amazonses.com for the sending domain. If we opt for this, we will need to add CNAME, TXT, and MX records to the DNS configuration for the domain.

Similarly to sending text messages with SNS, the SES account starts in a sandbox. The sandbox status imposes rate limits, restricts the number of emails, and includes other restrictions.

The sandbox is suitable for development and testing environments but AWS recommends requesting production access for production workloads.

3.2. Configure Simple Email Service for Cognito

We must then enable then email option as an Authentication method in the Cognito user pool.

Email authentication configuration
Email authentication configuration

The FROM email address should be the address we have already verified with SES. It should already be available on the dropdown list as an SES identity.

Optionally, we can configure the FROM sender name in the FirstName LastName <email@example.com> format. When users receive the email with the authentication code, this name, for example, John Doe will appear as the sender.

After we Save changes, the AWSServiceRoleForAmazonCognitoIdpEmailService will be created. The user pool will assume this role when calling Simple Email Service to send out the email:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "email.cognito-idp.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

The permissions policy is straighforward. It includes the AmazonCognitoIdpEmailServiceRolePolicy AWS-managed policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ses:SendEmail",
        "ses:SendRawEmail"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Deny",
      "Action": [
        "ses:List*"
      ],
      "Resource": "*"
    }
  ]
}

This role is necessary because AWS IAM verifies every AWS API call, even when one service invokes another service’s API, including SES SendEmail.

3.3. Enable USER_AUTH flow

We must also enable the USER_AUTH flow in the app client configuration if it hasn’t already been enabled.

Please see Part 1 for more information and a visual about this step.

3.4. Enable email sign-in

Next, we have to add Email OTP as an available sign-in option. Under the Sign-in menu on the left, we select Options for choice-based sign-in, and simply check the box next to Email message one-time password.

Configuring email sign-in option
Configuring email sign-in option

This completes the configuation. We can now add users who will authenticate via email to the user pool.

3.5. Add a user with email authentication option

When adding a user, we should ensure to include a valid email address.

Adding user with email
Adding user with email

Of course, we don’t need to add users manually. Cognito allows users to sign up by themselves. This post focuses on a demo with manual steps and does not cover the auto sign-up option.

3.6. Sign-in with email

When the user enters their username and clicks Next on the managed login page, the user pool will recognize that the user has a verified email address. Since we have enabled the email sign-in option, the next modal will prompt the user to Check your email and enter the verification code.

Prompt to enter the verification code received by email
Prompt to enter the verification code received by email

The email should arrive promptly. After entering the code in the input box, Cognito will respond with the ID and access tokens as expected. The authentication process is smooth, quick, and secure, and I haven’t experienced any latency. The management is happy once again!

4. Considerations

If we enable multiple sign-in options (password, text message, email), the managed login interface will offer the Try another way option. This allows the user to authenticate using any valid and enabled method.

5. Summary

We can configure email as a passwordless authentication option where users receive verification codes. Cognito can use Simple Email Service to send out these emails. However, we must configure SES before modifying any settings in the user pool.

The configuration process on the Cognito side is similar to setting up verification codes via text messages.

6. References, further reading

Getting started with user pools - How to create a user pool with an app client

Set up your SES account - Using the SES Wizard to quickly set up the account

Set up email sending with Amazon SES - Different ways of sending emails with SES