Page updated Nov 14, 2023

Add SMS flows

Note: If you create or update an SMS MFA configuration for your Cognito user pool, the Cognito service will send a test SMS message to an internal number in order to verify your configuration. You will be charged for these test messages by Amazon SNS.

For information about Amazon SNS pricing, see Worldwide SMS Pricing.

There are a few ways to integrate phone numbers into an Amplify project's sign-in and verification process.

  • As a username*: Users login with a username and password where their phone number acts as the username.
  • As a verification method: Users login by any means, but must verify their account with an OTP (one time password) sent to their phone.
  • MFA (Multi-Factor Authentication): Users must verify every login with an OTP sent to their phone.

*Note: This is different from using a phone number alias, which is currently unsupported by the Amplify CLI.

These methods may be combined with each other or used independently but they all require the same prerequisites for sending SMS messages via Amazon SNS, the notification service used by Amplify.

Prerequisites

Sandbox Mode

Upon enabling any of the above settings in Amplify, the CLI may prompt you with the following message:

1You have enabled SMS based auth workflow. Verify your SNS account mode in the SNS console: https://console.aws.amazon.com/sns/v3/home#/mobile/text-messaging
2If your account is in "Sandbox" mode, you can only send SMS messages to verified recipient phone numbers.

Follow the link to visit your SNS account. If your account is in "Sandbox" mode, you'll need to verify a phone number before you're able to send SMS messages.

Set up an Origination Entity

If you see the following banner at the top of your SNS homepage, you'll need to perform some additional steps before adding a phone number. If not, you can skip to Verify a Phone Number.

A warning stating that a valid origination ID must be registered to send SMS messages to US destinations.

Clicking Manage origination entities will bring you to Pinpoint, where you can register an originating entity. Depending on which country you'll be sending SMS messages from, you may choose to register either a Sender ID or an Origination number.

You can find the complete list of supported options for your country here.

Sender ID

If your country supports using sender IDs, follow the instructions here to request one and enable it in your account.

Origination number

If your country does not support sender IDs, you must purchase an origination number.

In Pinpoint, scroll to Number settings and click on Request phone number. This will bring you to a page where you can obtain a Toll-free number for sending SMS messages. Choose the country from which you'll be sending SMS messages, then follow the prompts for requesting a new number.

After successfully requesting a toll-free number, you can return to SNS to verify your phone number.

Verify a Phone Number

Return to SNS, and scroll to the Sandbox destination phone numbers section. Click Add phone number and follow the instructions to verify your phone number.

You are now ready to setup auth for OTP.

Setup

The following options are only available when starting a new project (via amplify add auth). You will not have access to these settings after creation (via amplify update).

  • Required MFA
  • Phone Number Sign-In

Run amplify add auth to create a new Cognito Auth resource, and follow the prompts below depending on how you want to integrate phone numbers into your flow.

As a username

By default, this will leave email verification enabled. If you would also like to use phone numbers for verifying users' accounts, follow the steps for As a verification method and choose Phone Number for the sign-in method when prompted.

1$ amplify add auth
2
3? Do you want to use the default authentication and security configuration?
4# Default configuration
5Warning: you will not be able to edit these selections.
6? How do you want users to be able to sign in?
7# Phone Number
8? Do you want to configure advanced settings?
9# No, I am done.
10
11Some next steps:
12"amplify push" will build all your local backend resources and provision it in the cloud
13"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud

As a verification method

Perform the following steps to disable email-based verification and enable SMS-based verification.

1$ amplify add auth
2
3? Do you want to use the default authentication and security configuration?
4# Manual configuration
5
6... Answer as appropriate
7
8? Email based user registration/forgot password:
9# Disabled (Uses SMS/TOTP as an alternative)
10? Please specify an SMS verification message:
11# Your verification code is {####}
12
13... Answer as appropriate
14
15Some next steps:
16"amplify push" will build all your local backend resources and provision it in the cloud
17"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud

SMS MFA

Turning MFA "ON" will make it required for all users, while "Optional" will make it available to enable on a per-user basis.

1$ amplify add auth
2
3? Do you want to use the default authentication and security configuration?
4# Manual configuration
5
6... Answer as appropriate
7
8? Multifactor authentication (MFA) user login options:
9# ON (Required for all logins, can not be enabled later)
10? For user login, select the MFA types:
11# SMS Text Message
12? Please specify an SMS authentication message:
13# Your authentication code is {####}
14
15... Answer as appropriate
16
17Some next steps:
18"amplify push" will build all your local backend resources and provision it in the cloud
19"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud

Run amplify update auth and follow the prompts as guided below.

As a username

The type of username used for signing in cannot be changed after creating a user pool. If needed, first run amplify remove auth to delete the existing user pool, then follow the New Project flow on this page for enabling phone-number sign-in.

As a verification method

Perform the following steps to disable email-based verification and enable SMS-based verification.

Note: After making this change, email may still be required when signing up users if it was marked as a required attribute when creating the user pool. This will be true if the Default configuration was chosen when running amplify add auth. If so, it must be included with userAttributes in the sign up options.

1$ amplify update auth
2
3? What do you want to do?
4# Walkthrough all the auth configurations
5
6... Answer as appropriate
7
8? Email based user registration/forgot password:
9# Disabled (Uses SMS/TOTP as an alternative)
10? Please specify an SMS verification message:
11# Your verification code is {####}
12
13... Answer as appropriate
14
15Some next steps:
16"amplify push" will build all your local backend resources and provision it in the cloud
17"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud

SMS MFA

As mentioned above, MFA cannot be unconditionally enabled for all users after creating a user pool. The following steps show how to enable MFA as "Optional" for users. In this mode, MFA must be enabled on a user-by-user basis, either through an Admin SDK (e.g. via a Lambda trigger as part of the sign-up process), or manually in the Cognito console.

If you'd like to make MFA required for users, you must first delete your auth resource by running amplify remove auth, then follow the New Project flow on this page.

1$ amplify update auth
2
3? What do you want to do?
4# Walkthrough all the auth configurations
5
6... Answer as appropriate
7
8? Multifactor authentication (MFA) user login options:
9# OPTIONAL (Individual users can use MFA)
10? For user login, select the MFA types:
11# SMS Text Message
12? Please specify an SMS authentication message:
13# Your authentication code is {####}
14
15... Answer as appropriate
16
17Some next steps:
18"amplify push" will build all your local backend resources and provision it in the cloud
19"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud

Sign Up

Sign up users normally with the chosen Username type and password. Certain attributes may be required in the userAttributes map depending on the options chosen above:

  • "email" is required if:
    • One of the following are true:
      • Email verification is enabled (default)
      • Email was marked as a required attribute (default)
    • and users sign up with a chosen username or phone number
  • "phone_number" is required if:
    • One of the following are true:
      • MFA is ON, or manually enabled for the user
      • Phone number verification is enabled
      • Phone number was marked as a required attribute
    • and users sign up with a chosen username or email
1AuthSignUpOptions options = AuthSignUpOptions.builder()
2 .userAttribute(AuthUserAttributeKey.email(), "my@email.com")
3 .userAttribute(AuthUserAttributeKey.phoneNumber(), "+18885551234")
4 .build();
5Amplify.Auth.signUp("username", "Password123", options,
6 result -> Log.i("AuthQuickStart", "Result: " + result.toString()),
7 error -> Log.e("AuthQuickStart", "Sign up failed", error)
8);
1val options = AuthSignUpOptions.builder()
2 .userAttribute(AuthUserAttributeKey.email(), "my@email.com")
3 .userAttribute(AuthUserAttributeKey.phoneNumber(), "+18885551234")
4 .build()
5Amplify.Auth.signUp("username", "Password123", options,
6 { Log.i("AuthQuickStart", "Sign up succeeded: $it") },
7 { Log.e ("AuthQuickStart", "Sign up failed", it) }
8)
1val options = AuthSignUpOptions.builder()
2 .userAttribute(AuthUserAttributeKey.email(), "my@email.com")
3 .userAttribute(AuthUserAttributeKey.phoneNumber(), "+18885551234")
4 .build()
5try {
6 val result = Amplify.Auth.signUp("username", "Password123", options)
7 Log.i("AuthQuickStart", "Result: $result")
8} catch (error: AuthException) {
9 Log.e("AuthQuickStart", "Sign up failed", error)
10}
1RxAmplify.Auth.signUp(
2 "username",
3 "Password123",
4 AuthSignUpOptions.builder()
5 .userAttribute(AuthUserAttributeKey.email(), "my@email.com")
6 .userAttribute(AuthUserAttributeKey.phoneNumber(), "+18885551234")
7 .build())
8 .subscribe(
9 result -> Log.i("AuthQuickStart", "Result: " + result.toString()),
10 error -> Log.e("AuthQuickStart", "Sign up failed", error)
11 );

Verification of user accounts is done via the confirmSignUp method with the OTP sent to their phone or email.

1Amplify.Auth.confirmSignUp(
2 "username",
3 "the code you received",
4 result -> Log.i("AuthQuickstart", result.isSignUpComplete() ? "Confirm signUp succeeded" : "Confirm sign up not complete"),
5 error -> Log.e("AuthQuickstart", error.toString())
6);
1Amplify.Auth.confirmSignUp(
2 "username", "the code you received",
3 { result ->
4 if (result.isSignUpComplete) {
5 Log.i("AuthQuickstart", "Confirm signUp succeeded")
6 } else {
7 Log.i("AuthQuickstart","Confirm sign up not complete")
8 }
9 },
10 { Log.e("AuthQuickstart", "Failed to confirm sign up", it) }
11)
1try {
2 val code = "code you received"
3 val result = Amplify.Auth.confirmSignUp("username", code)
4 if (result.isSignUpComplete) {
5 Log.i("AuthQuickstart", "Signup confirmed")
6 } else {
7 Log.i("AuthQuickstart", "Signup confirmation not yet complete")
8 }
9} catch (error: AuthException) {
10 Log.e("AuthQuickstart", "Failed to confirm signup", error)
11}
1RxAmplify.Auth.confirmSignUp("username", "the code you received")
2 .subscribe(
3 result -> Log.i("AuthQuickstart", result.isSignUpComplete() ? "Confirm signUp succeeded" : "Confirm sign up not complete"),
4 error -> Log.e("AuthQuickstart", error.toString())
5 );

You will know the sign up flow is complete if you see the following in your console window:

1Confirm signUp succeeded

Sign In

Sign in users normally with the chosen Username type and password.

1Amplify.Auth.signIn(
2 "username",
3 "password",
4 result -> {
5 if (result.getNextStep().getSignInStep() == AuthSignInStep.CONFIRM_SIGN_IN_WITH_SMS_MFA_CODE &&
6 result.getNextStep().getCodeDeliveryDetails() != null) {
7 String destination = result.getNextStep().getCodeDeliveryDetails().getDestination();
8 Log.d("SignIn", "SMS code sent to "+ destination);
9 Log.d("SignIn", "Additional Info" + result.getNextStep().getAdditionalInfo());
10
11 // Prompt the user to enter the SMSMFA code they received
12 // Then invoke `confirmSignIn` api with the code
13 }
14 },
15 error -> Log.e("AuthQuickstart", error.toString())
16);
1Amplify.Auth.signIn("username", "password",
2 { result ->
3 if (result.nextStep.signInStep == AuthSignInStep.CONFIRM_SIGN_IN_WITH_SMS_MFA_CODE) {
4 val destination = result.nextStep.codeDeliveryDetails?.destination
5 Log.d("SignIn", "SMS code sent to $destination")
6 Log.d("SignIn", "Additional Info $result.nextStep.additionalInfo")
7
8 // Prompt the user to enter the SMSMFA code they received
9 // Then invoke `confirmSignIn` api with the code
10 }
11 },
12 { Log.e("AuthQuickstart", "Failed to sign in", it) }
13)
1try {
2 val result = Amplify.Auth.signIn("username", "password")
3 if (result.nextStep.signInStep == AuthSignInStep.CONTINUE_SIGN_IN_WITH_TOTP_SETUP) {
4 val destination = result.nextStep.codeDeliveryDetails?.destination
5 Log.d("SignIn", "SMS code sent to $destination")
6 Log.d("SignIn", "Additional Info $result.nextStep.additionalInfo")
7
8 // Prompt the user to enter the SMSMFA code they received
9 // Then invoke `confirmSignIn` api with the code
10 }
11} catch (error: AuthException) {
12 Log.e("AuthQuickstart", "Sign in failed", error)
13}
1RxAmplify.Auth.signIn("username", "password")
2 .subscribe(
3 result -> {
4 if (result.getNextStep().getSignInStep() == AuthSignInStep.CONTINUE_SIGN_IN_WITH_TOTP_SETUP &&
5 result.getNextStep().getCodeDeliveryDetails() != null) {
6 String destination = result.getNextStep().getCodeDeliveryDetails().getDestination();
7 Log.d("SignIn", "SMS code sent to " + destination);
8 Log.d("SignIn", "Additional Info " + result.getNextStep().getAdditionalInfo());
9
10 // Prompt the user to enter the SMSMFA code they received
11 // Then invoke `confirmSignIn` api with the code
12 }
13 },
14 error -> Log.e("AuthQuickstart", error.toString())
15 );

If MFA is ON or enabled for the user, you must call confirmSignIn with the OTP sent to their phone.

1Amplify.Auth.confirmSignIn(
2 "Confirmation code received via SMS",
3 result -> Log.i("AuthQuickstart", result.toString()),
4 error -> Log.e("AuthQuickstart", error.toString())
5);
1Amplify.Auth.confirmSignIn("Confirmation code received via SMS",
2 { Log.i("AuthQuickstart", "Confirmed signin: $it") },
3 { Log.e("AuthQuickstart", "Failed to confirm signin", it) }
4)
1try {
2 val result = Amplify.Auth.confirmSignIn("Confirmation code received via SMS")
3 Log.i("AuthQuickstart", "Confirmed signin: $result")
4} catch (error: AuthException) {
5 Log.e("AuthQuickstart", "Failed to confirm signin", error)
6}
1RxAmplify.Auth.confirmSignIn("Confirmation code received via SMS")
2 .subscribe(
3 result -> Log.i("AuthQuickstart", result.toString()),
4 error -> Log.e("AuthQuickstart", error.toString())
5 );