In my previous article, Passwordless SMS Authentication: The Basics I talked about the three factors of authentication and using something you possess, such as a mobile phone capable of receiving SMS text messages for authentication without ever knowing a password. Providing passwordless SMS authentication is still one of the simplest ways to onboard your users. In this article, we’ll walk through implementing the backend solution for a custom passwordless SMS authentication flow using Amazon Cognito.

Solution

This solution involves setting up a Cognito user pool with a custom auth challenge flow using three Lambda function triggers (plus one function to auto-confirm the user’s phone number as username). Since the process of creating this custom auth flow has many moving pieces, to say the least, I built a one-click solution so that you can deploy the entire backend via the AWS Serverless Application Repository. With the time saved in deploying this solution, I’ll walk you through each function and the role each plays in the login flow.

Overview of the solution

Btw — This is the best practice for implementing passwordless SMS (or email) according to documentation via Amazon Cognito user pools with Custom Authentication Challenge Lambda Triggers.

This solution follows the flow as outlined in the above docs. We’ll be using an Amazon Cognito user pool and a set of AWS Lambda functions as triggers to complete a custom authentication flow. We’ll be using Amazon SNS for sending one-time codes (aka one-time-passcodes or OTP) to users via SMS text messages. Below is the diagram of the custom auth flow showing each Lambda function. We’ll build the ‘App user’ client solution in the next article.

The diagram is a depiction of these following steps a mobile/web user goes through to complete the auth flow.

1. The user enters their phone number on the custom sign-up/sign-in page, which sends it to your Amazon Cognito user pool.

2. The user pool calls the “Define Auth Challenge” Lambda function. This Lambda function determines which custom challenge needs to be created.

3. The user pool calls the “Create Auth Challenge” Lambda function. This Lambda function generates a secret login code and sends this code to the user’s mobile device via SMS using Amazon SNS as the transport service.

4. The user retrieves the secret login code on their phone and enters it into the custom sign-in page, which is then sent back and your user pool calls the “Verify Auth Challenge Response” Lambda function to verify the users’ response.

5. The user pool calls the “Define Auth Challenge” Lambda function again to verify that the challenge has been successfully answered and that no further challenge is needed. The function includes “issueTokens: true” in its response to the user pool. The user pool now considers the user to be authenticated and sends valid JSON Web Tokens (JWTs) in the final response to the user.

Note: For native iOS and Android developers using the native AWS SDK, you don’t need to worry about handling the JWT tokens as the AWSMobileClient manages all this for you by passing the tokens over to Cognito Identity Pool in exchange for AWS credentials. More on this in the next article where I’ll be implementing an iOS native app that follows this exact flow from beginning to end and uses the mobile SDK for iOS to retrieve AWS credentials in exchange for the received JWT tokens using Amazon Cognito Identity Pool.