We can use Cognito user pools to create passwordless user authentication flows for our applications. One option is to receive a verification code in a text message.
1. Problem statement
Alice has been assigned a new project involving a business need for passwordless authentication in one of the company's applications. Some managers believe passwords are outdated and less secure compared to passwordless options.
The application currently uses a Cognito user pool for user authentication. At present, users sign in using their username and password. However, it is now a requirement to provide new users with the option of passwordless authentication by receiving a verification code via SMS.
Alice's task is to research the SMS passwordless sign-in option in Cognito and present her findings to management.
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.
- An IAM role.
Additionally, it does not detail how to send SMS messages using SNS.
Links to the relevant documentation pages will be provided at the end of the post for those who need them.
To enable passwordless authentication, the Cognito user pool must be on either the Essentials (default for new user pools) or the Plus feature plan.
3. Passwordless Authentication with SMS
Here's how we can configure Cognito to send text messages to users' phones.
3.1. Configure SNS for Cognito
Cognito relies on Simple Notification Service (SNS) to send SMS messages. The first step is to connect SNS with Cognito.
Since every API call in AWS requires permissions, even for interactions between services, we need to configure these permissions in AWS Identity and Access Management (IAM).
The user pool will assume a role to interact with SNS. Fortunately, Cognito can create this role automatically. In the user pool's menu, under Authentication methods, select SMS and choose the Create a new IAM role option.
The required permissions policy must allow the sns:Publish
action:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sns:publish"
],
"Resource": [
"*"
]
}
]
}
The trust policy for the role specifies who can assume it:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "cognito-idp.amazonaws.com"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "UNIQUE_EXTERNAL_ID"
}
}
}
]
}
This trust policy allows the role to be assumed by Cognito user pools (indicated by the Principal
element). However, this is restricted to cases where the external ID in the AssumeRole
API request matches the value of the sts:ExternalId
key in the trust policy.
The external ID is a globally unique identifier (GUID) generated by Cognito when the role is created. It ensures that only the specific user pool associated with this role can assume it. I plan to explore external IDs and the confused deputy problem in more detail in a separate post.
To view the external ID for a user pool, we can call the DescribeUserPool
API:
{
"UserPool": {
"SmsConfiguration": {
"SnsCallerArn": "arn:aws:iam::ACCOUNT_ID:role/service-role/ROLE_NAME",
"ExternalId": "UNIQUE_EXTERNAL_ID",
"SnsRegion": "eu-central-1"
},
// Other properties in the response have been omitted
}
}
As a result, other user pools can't assume this role, as their external IDs will differ.
3.2. From SMS Sandbox to production
Amazon SNS places new SMS accounts into a sandbox for security reasons. While the account is in the sandbox, text messages can only be delivered to a maximum of 10 verified phone numbers.
The sandbox is useful for development and testing purposes but is unsuitable for a production environment where hundreds or thousands of users need to receive text messages. For this reason, you may want to transition the account from the sandbox to the production environment. More information about this process can be found in the links section at the bottom of the page.
3.3. Enable the passwordless option
Under the Authentication section, we can enable one or more passwordless options. Available choices include Passkey, Email message one-time password, and SMS message one-time password. Multiple options can be selected, but for now, let's proceed with the SMS message.
3.4. Modify the App Client
Next, we must enable the USER_AUTH
flow in the app client configuation if it has not already been enabled.
This can be done by selecting the checkbox next to the ALLOW_USER_AUTH
setting under the Authentication flows section in the App client menu. This configuration allows users to sign in using methods other than a username and password, such as a one-time passcode (OTP), which aligns with our passwordless authentication goal.
3.5. Create a user without a password
We can now create a user with a phone number, or they can sign up using their phone number if this option is enabled in the user pool.
If you are using a sandbox environment, ensure that a verified phone number is added to the user. To make the verification code received via SMS the sole authentication method, set the Temporary password to Don't set a password.
3.6. It works!
When we call the authorization server endpoint, which ends in /oauth2/authorize
, the managed UI will display only the username field.
Enter the username of the newly created user configured to sign in exclusively with a passcode. Next, the UI will prompt for the verification code sent to the user's specified phone number.
If, however, we attempt to log in a user with a password as their only sign-in option, clicking Next in the Sign in pop-up will automatically display the Password field. Cognito user pools dynamically determine which input field to show based on the username provided.
4. Considerations
It's possible to add the text message option and other passwordless options to a newly created user pool, so using an existing user pool is not mandatory.
What if we want a single user to have both password and SMS-code options? Will it work?
Yes. If a user is created with both password and phone number sign-in enabled, the managed UI will display the Try another way option.
Here, users can select from the available options, such as SMS one-time password and Password. The user can then decide how they want to authenticate.
5. Summary
Cognito user pools offer passwordless sign-in options for application users. One of these options is a verification code sent via text message.
The user pool utilizes SNS to send text messages to phone numbers. Configuring this involves several steps, including setting up permissions in both SNS and Cognito, moving the account out of the sandbox for production, and enabling the SMS passwordless option in the user pool. Once configured, the managed UI will automatically display the appropriate sign-in page based on the user's settings.
6. References, further reading
Getting started with user pools - How to create a user pool with an app client
IAM role creation - How to create IAM roles
Sending SMS messages using Amazon SNS - The title says it all
Moving out of the Amazon SNS SMS sandbox - The process to send text messages to any phone numbers from SNS
Top comments (0)