Page updated Feb 29, 2024

Manage MFA settings

The Auth category supports Multi-factor Authentication (MFA) for user sign-in flows. MFA is an extra layer of security used to make sure that users trying to gain access to an account are who they say they are. It requires users to provide additional information to verify their identity. Amplify Auth supports the MFA methods with Time-based-One-Time Passwords (TOTP) as well as text messages (SMS). In this guide we will review how you can set up MFA using TOTP and SMS and the tradeoffs between these methods to help you choose the right set up for your application. We’ll also review how to set up MFA to remember a device and reduce sign-in friction for your users.

Before you begin, you will need:

  • The Amplify libraries installed and configured
  • Optional If you are using SMS you will need a phone number provisioned with an SNS/Pinpoint

Enable multi-factor authentication

Below are the steps you can use to set up MFA using SMS or TOTP with the Amplify CLI. The Amplify libraries are designed to work with MFA even if you have set up your Amazon Cognito resources separately.

You can also use the Amazon Cognito console to enable MFA. You will first enable MFA for your Cognito User Pool and then set up MFA for your app. Please see the Amazon Cognito Developer Guide for more information to set up MFA in Amazon Cognito. You can use the same Cognito console to enable or disable MFA.

Understand your MFA options

When enabling MFA you will have two key decisions to make:

  • MFA enforcement: As part of this setup you will determine how MFA is enforced. If you require MFA by setting MFA login to "ON", all your users will need to complete MFA to sign in. If you keep it "Optional", your users will have the choice whether to enable MFA or not for their account.
  • MFA methods: You will also specify which MFA method you are using - TOTP (Time-based One-time Password), SMS (text message), or both. We recommend that you use TOTP-based MFA as it is more secure and you can reserve SMS for account recovery.
Learn more
Compare TOTP and SMS MFA methods
Time-based One-time Password (TOTP)Short Message Service (SMS)
DescriptionGenerates a short-lived numeric code for user authentication that includes a shared secret key and current time using an authenticator app.Generates a one-time code shared via text message that is entered with other credentials for user authentication.
BenefitsMore secure than SMS since the code is generated locally and not transmitted over a network. TOTP also works without cell service as long as the TOTP app is installed.Easy to set up with a user-provided phone number and is familiar to users as a common authentication method.
ConstraintsRequires an app to generate codes and adds to the initial setup of an account. Codes also expire quickly and must be used promptly after it is generated.SMS requires cell service and can include an additional cost for the user. Although rare, SMS messages can also be intercepted.

Enable MFA with the Amplify CLI

Note: If your User Pool was created using Amplify CLI to set up backend resources (via amplify add auth) and you did not enable MFA, you will only be able to select the 'OPTIONAL' configuration for MFA when updating (via amplify update auth). Similarly, once MFA is enabled for a User pool you cannot disable it (via amplify update auth).

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

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

SMS MFA

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.

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

TOTP MFA

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 Time-Based One-Time Password (TOTP)
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

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

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.

SMS MFA

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.

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

TOTP MFA

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 Time-Based One-Time Password (TOTP)
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

After you enable MFA you will also need to include MFA setup when users sign up. This will change depending on if you enable SMS, TOTP or both.

Set up MFA with SMS

Once you have setup SMS as your second layer of authentication with MFA as shown above, your users will get an authentication code via a text message to complete sign-in after they sign in with their username and password.

If you do not have one already, you will need to configure an IAM role to use with Amazon Simple Notification Service (Amazon SNS) to manage SMS messages. You will then add this role under the "Messaging" tab for your user pool in the Amazon Cognito console. For additional information see the Amazon Cognito SMS text message MFA documentation.

Enable SMS MFA during sign-up

You will need to pass phone_number as a user attribute to enable SMS MFA for your users during sign-up. However, if the primary sign-in mechanism for your Cognito resource is phone_number (without enabling username), then you do not need to pass it as an attribute.

1import { Auth } from 'aws-amplify';
2
3async function signIn() {
4 try {
5 const user = await Auth.signUp({
6 username,
7 password,
8 attributes: {
9 phone_number: '+15558675309' // Replace with a valid phone number
10 }
11 });
12 } catch (err) {
13 console.log(error);
14 }
15}
1import { Auth } from 'aws-amplify';
2
3async function signIn() {
4 try {
5 const user = await Auth.signUp({
6 username,
7 password,
8 attributes: {
9 phone_number: '+15558675309' // Replace with a valid phone number
10 }
11 });
12 } catch (err) {
13 console.log(error);
14 }
15}

By default, you have to verify a user account after they sign up using the confirmSignUp API, which will send a one-time password to the user's phone number or email, depending on your Amazon Cognito configuration.

1import { Auth } from 'aws-amplify';
2
3async function confirmSignUp() {
4 try {
5 await Auth.confirmSignUp(username, code);
6 } catch (error) {
7 console.log('error confirming sign up', error);
8 }
9}
1import { Auth } from 'aws-amplify';
2
3async function confirmSignUp() {
4 try {
5 await Auth.confirmSignUp(username, code);
6 } catch (error) {
7 console.log('error confirming sign up', error);
8 }
9}

Manage SMS MFA during sign-in

After a user signs in, if they have MFA enabled for their account, a challenge will be returned that needs to call the confirmSignIn API where the user provides their confirmation code sent to their phone number. Amplify will then verify with Cognito that the SMS code is valid and complete the sign-in process by returning access, ID, and refresh tokens that are all handled by Amplify internally. Once the user completes the SMS text message flow their phone number is marked as verified in your user pool.

In the example below you will see that because MFA is "ON" or enabled as an option for the user, you must call confirmSignIn with the OTP sent to their phone. After a user has been signed in, you can call setPreferredMFA to record the MFA type as enabled for the user and set it as preferred so that subsequent logins default to using this MFA type.

1import { Auth } from 'aws-amplify';
2
3type ConfirmSignInWithMFAParameters = {
4 username: string;
5 password: string;
6};
7
8type MFAType = 'SMS_MFA';
9
10async function signInWithMFA({
11 username,
12 password
13}: ConfirmSignInWithMFAParameters) {
14 try {
15 const user = await Auth.signIn(username, password);
16 if (
17 user.challengeName === 'SMS_MFA' ||
18 user.challengeName === 'SOFTWARE_TOKEN_MFA'
19 ) {
20 // You need to get the code from the UI inputs
21 // and then trigger the following function with a button click.
22 const code: string = await getCodeFromUserInput();
23 const mfaType: MFAType = await getMFATypeFromUserInput();
24 // If MFA is enabled, sign-in should be confirmed with the confirmation code:
25 const loggedUser = await Auth.confirmSignIn(
26 user, // Return object from Auth.signIn()
27 code, // Confirmation code
28 mfaType // MFA Type e.g. SMS_MFA, SOFTWARE_TOKEN_MFA
29 );
30 console.log(loggedUser);
31 } else {
32 // The user directly signs in:
33 console.log(user);
34 }
35 } catch (error) {
36 console.log(`error signing in`, error);
37 }
38}
39
40async function getCodeFromUserInput(): Promise<string> {
41 // fetch code using a user form input
42}
43async function getMFATypeFromUserInput(): Promise<MFAType> {
44 // fetch MFA type from user form input
45}
1import { Auth } from 'aws-amplify';
2
3async function signInWithMFA() {
4 try {
5 const user = await Auth.signIn(username, password);
6 if (
7 user.challengeName === 'SMS_MFA' ||
8 user.challengeName === 'SOFTWARE_TOKEN_MFA'
9 ) {
10 // You need to get the code from the UI inputs
11 // and then trigger the following function with a button click.
12 const code = getCodeFromUserInput();
13 const mfaType = getMFATypeFromUserInput();
14 // If MFA is enabled, sign-in should be confirmed with the confirmation code
15 const loggedUser = await Auth.confirmSignIn(
16 user, // Return object from Auth.signIn()
17 code, // Confirmation code
18 mfaType // MFA Type e.g. SMS_MFA, SOFTWARE_TOKEN_MFA
19 );
20 console.log(loggedUser);
21 } else {
22 // The user directly signs in
23 console.log(user);
24 }
25 } catch (error) {
26 console.log(`error signing in`, error);
27 }
28}

Set up MFA with TOTP

You can use Time-based One-Time Password (TOTP) for multi-factor authentication (MFA) in your web or mobile applications. The Amplify Auth category includes support for TOTP setup and verification using authenticator apps, offering an integrated solution and enhanced security for your users. These apps, such as Google Authenticator or Microsoft Authenticator, have the TOTP algorithm built-in and work by using a shared secret key and the current time to generate short-lived, six digit passwords.

Enable TOTP for your users

If you initiate a user sign-in with the signIn API where your user is required to set up TOTP as an MFA method, the API call will return setupTOTP as a challenge and next step to handle in your app. You will get that challenge if the following conditions are met:

  • MFA is marked as "Required" in Cognito User Pool.
  • TOTP is enabled in the Cognito User Pool
  • The user does not have TOTP MFA set up already.

You can set up TOTP for a user in your app with the setupTOTP API. As part of this workflow you can also specify how users see the code retrieved from the authenticator app (e.g. numeric code or QR code), confirm the initial setup with the authenticator app, set TOTP as the preferred MFA method, and pass the TOTP code with the MFA type using the confirmSignIn API:

1import { CognitoUserSession } from 'amazon-cognito-identity-js';
2import { Auth } from 'aws-amplify';
3
4type SetupTOTPAuthParameters = {
5 user: string;
6 challengeAnswer: string;
7 mfaType?: 'SMS_MFA' | 'SOFTWARE_TOKEN_MFA';
8};
9
10async function setupTOTPAuth({
11 user,
12 challengeAnswer,
13 mfaType
14}: SetupTOTPAuthParameters) {
15 // To set up TOTP, first you need to get a `authorization code` from Amazon Cognito.
16 // `user` is the current Authenticated user:
17 const secretCode = await Auth.setupTOTP(user);
18
19 // You can directly display the `code` to the user or convert it to a QR code to be scanned.
20 // For example, use following code sample to render a QR code with `qrcode.react` component:
21 // import QRCodeCanvas from 'qrcode.react';
22 // const str = "otpauth://totp/AWSCognito:"+ username + "?secret=" + secretCode + "&issuer=" + issuer;
23 // <QRCodeCanvas value={str}/>
24
25 // ...
26
27 // Then you will have your TOTP account in your TOTP-generating app (like Google Authenticator)
28 // use the generated one-time password to verify the setup.
29 try {
30 const cognitoUserSession: CognitoUserSession = await Auth.verifyTotpToken(
31 user,
32 challengeAnswer
33 );
34 // Don't forget to set TOTP as the preferred MFA method.
35 await Auth.setPreferredMFA(user, 'TOTP');
36 } catch (error) {
37 // Token is not verified
38 }
39
40 // ...
41
42 // Finally, when sign-in with MFA is enabled, use the `confirmSignIn` API
43 // to pass the TOTP code and MFA type.
44 const OTPCode = '123456'; // Code retrieved from authenticator app.
45 await Auth.confirmSignIn(user, OTPCode, mfaType); // Optional, MFA Type e.g. SMS_MFA || SOFTWARE_TOKEN_MFA
46}
1import { Auth } from 'aws-amplify';
2
3async function setupTOTPAuth(user, challengeAnswer, mfaType) {
4 // To set up TOTP, first you need to get a `authorization code` from Amazon Cognito.
5 // `user` is the current Authenticated user:
6 const OTPCode = '123456'; // Code retrieved from authenticator app.
7
8 // You can directly display the `code` to the user or convert it to a QR code to be scanned.
9 // For example, use following code sample to render a QR code with `qrcode.react` component:
10 // import QRCodeCanvas from 'qrcode.react';
11 // const str = "otpauth://totp/AWSCognito:"+ username + "?secret=" + code + "&issuer=" + issuer;
12 // <QRCodeCanvas value={str}/>
13
14 // ...
15
16 // Then you will have your TOTP account in your TOTP-generating app (like Google Authenticator)
17 // use the generated one-time password to verify the setup.
18 try {
19 const cognitoUserSession = await Auth.verifyTotpToken(
20 user,
21 challengeAnswer
22 );
23 // Don't forget to set TOTP as the preferred MFA method.
24 await Auth.setPreferredMFA(user, 'TOTP');
25 } catch (error) {
26 // Token is not verified
27 }
28
29 // ...
30
31 // Finally, when sign-in with MFA is enabled, use the `confirmSignIn` API
32 // to pass the TOTP code and MFA type.
33 await Auth.confirmSignIn(user, code, mfaType); // Optional, MFA Type e.g. SMS_MFA || SOFTWARE_TOKEN_MFA
34}

Once the authenticator app is set up, the user can generate a TOTP code and provide it to the library to complete the sign in process.

Learn more
Enable TOTP after a user is signed in

TOTP MFA can be set up after a user has signed in. This can be done when the following conditions are met:

  • MFA is marked as "Optional" or "Required" in the Cognito User Pool
  • TOTP is marked as an enabled MFA method in Cognito user pool

TOTP can be set up by calling the setupTOTP and verifyTotpToken APIs in the Auth category.

Invoke the setupTOTP API to generate a SetupTOTPAuthParameters object which should be used to configure an authenticator app like Microsoft Authenticator or Google Authenticator. For more advanced use cases, SetupTOTPAuthParameters also contains a secretCode which can be used to either generate a QR code or be manually entered into an authenticator app. Once the authenticator app is set up, the user must generate a TOTP code and provide it to the library. Pass the code to verifyTotpToken to complete the TOTP setup process.

Recover from a lost TOTP device

If a user loses access to their TOTP device, they will need to contact an administrator to get help accessing their account. Based on the Cognito User Pool configuration, the administrator can use the AdminSetUserMFAPreference to either change the MFA preference to a different MFA method or to disable MFA for the user.

In a scenario where MFA is marked as "Required" in the Cognito User Pool and another MFA method is not set up, the administrator would need to first initiate an AdminUpdateUserAttributes call and update the user’s phone number attribute. Once this is complete, the administrator can continue changing the MFA preference to SMS as suggested above.

Set up a user's preferred MFA method

Since both SMS MFA and TOTP MFA methods are supported by Amazon Cognito, you can provide the option for your users to choose their second authentication factor or opt out. When both are available you will need to also save their preference for future sessions with the setupMFAType API:

1import { Auth } from 'aws-amplify';
2
3type PreferredMFAType = 'TOTP' | 'SMS' | 'NOMFA';
4
5async function setupMFAType(preferredMFA: PreferredMFAType) {
6 try {
7 const user = await Auth.currentAuthenticatedUser();
8 const data = await Auth.setPreferredMFA(user, preferredMFA);
9 console.log(data);
10 } catch (error) {
11 console.log('error setting up MFA type', error);
12 }
13}
14
15// Select TOTP as preferred.
16setupMFAType('TOTP');
17
18// Select SMS as preferred.
19setupMFAType('SMS');
20
21// Select no MFA.
22setupMFAType('NOMFA');
1import { Auth } from 'aws-amplify';
2
3async function setupMFAType(preferredMFA) {
4 try {
5 const user = await Auth.currentAuthenticatedUser();
6 const data = await Auth.setPreferredMFA(user, preferredMFA);
7 console.log(data);
8 } catch (error) {
9 console.log('error setting up MFA type', error);
10 }
11}
12
13// Select TOTP as preferred.
14setupMFAType('TOTP');
15
16// Select SMS as preferred.
17setupMFAType('SMS');
18
19// Select no MFA.
20setupMFAType('NOMFA');

Retrieve current preferred MFA method

Once the preferred MFA method is set for your user you will then want to use the getPreferredMFAType method to call this preference for future sign-in confirmations:

1import { Auth } from 'aws-amplify';
2
3async function getPreferredMFAType() {
4 try {
5 // Will retrieve the current MFA type from cache
6 // `bypassCache` is optional and by default is false.
7 // If set to true, it will get the MFA type from server-side
8 // instead of from local cache.
9 const user = await Auth.currentAuthenticatedUser();
10 const data = await Auth.getPreferredMFA(user, { bypassCache: false });
11 console.log('Current preferred MFA type is: ' + data);
12 } catch (err) {
13 console.log(err);
14 }
15}
1import { Auth } from 'aws-amplify';
2
3async function getPreferredMFAType() {
4 try {
5 // Will retrieve the current MFA type from cache
6 // `bypassCache` is optional and by default is false.
7 // If set to true, it will get the MFA type from server-side
8 // instead of from local cache.
9 const user = await Auth.currentAuthenticatedUser();
10 const data = await Auth.getPreferredMFA(user, { bypassCache: false });
11 console.log('Current preferred MFA type is: ' + data);
12 } catch (err) {
13 console.log(err);
14 }
15}

Only one MFA method can be marked as preferred at a time. If the user has multiple MFA methods enabled and tries to mark more than one MFA method as preferred, the API will throw an error. To avoid unexpected responses from Cognito, it is recommended to call Auth.setPreferredMFA() to ensure a user has set their MFA method before retrieving MFA settings with Auth.getPreferredMFA().

You can now enable multi-factor authentication and specify your second authentication method with TOTP or SMS. Your users can set their preferred method and you can retrieve this for them when they sign in. You can now look to add features like remembering a device to reduce friction in the sign-in workflow.

Remember a device

Remembering a device is useful in conjunction with MFA because it allows the second factor requirement to be automatically met when your user signs in on that device and reduces friction in their sign-in experience.

Note: The device tracking and remembering features are currently not available within the library when using the federated OAuth flow with Cognito User Pools or Hosted UI.

Configure device tracking

You can enable the remembered device functionality in the Cognito User Pool console. To begin, go to your project directory and issue the command:

1amplify auth console

Select the following option to open the Cognito User Pool console:

1? Which Console
2 User Pool

When the console opens, scroll down to the "Device Tracking" section and select the "Edit" button. This will render the following page allowing you to configure your preference for remembering a user's device.

Edit device tracking options list is shown, with the don't remember highlighted.

Choose either "Always remember" to remember a user's device by default or "User Opt-in" to give the user the ability to choose.

When MFA is enabled you will have the option to suppress the second factor during multi-factor authentication. Choose "Yes" if you want a remembered device to be used as a second factor mechanism.

Options for allow users to bypass MFA for trusted devices.

When you have made your selection(s), click "Save changes". You are now ready to start updating your code to manage remembered devices.

Learn more
Understand key terms used for tracking devices

There are differences to keep in mind when working with remembered, forgotten, and tracked devices.

  • Tracked: Every time the user signs in with a new device, the client is given the device key at the end of a successful authentication event. We use this device key to generate a salt and password verifier which is used to call the ConfirmDevice API. At this point, the device is considered to be "tracked". Once the device is in a tracked state, you can use the Amazon Cognito console to see the time it started to be tracked, last authentication time, and other information about that device.
  • Remembered: Remembered devices are also tracked. During user authentication, the device key and secret pair assigned to a remembered device is used to authenticate the device to verify that it is the same device that the user previously used to sign in.
  • Not Remembered: A not-remembered device is a tracked device where Cognito has been configured to require users to "Opt-in" to remember a device but the user has chosen not to remember the device. This use case is for users signing into their application from a device that they don't own.
  • Forgotten: In the event that you no longer want to remember or track devices, you can use the Auth.forgetDevice() API to remove devices from being both remembered and tracked.

Remember devices

You can remember devices using the following:

1import { Auth } from 'aws-amplify';
2
3async function rememberDevice() {
4 try {
5 const result = await Auth.rememberDevice();
6 console.log(result);
7 } catch (error) {
8 console.log('Error remembering device', error);
9 }
10}
1import { Auth } from 'aws-amplify';
2
3async function rememberDevice() {
4 try {
5 const result = await Auth.rememberDevice();
6 console.log(result);
7 } catch (error) {
8 console.log('Error remembering device', error);
9 }
10}

Forget devices

You can also forget devices but note that forgotten devices are neither remembered nor tracked.

1import { Auth } from 'aws-amplify';
2
3async function forgetDevice() {
4 try {
5 await Auth.forgetDevice();
6 } catch (error) {
7 console.log('Error forgetting device', error);
8 }
9}
1import { Auth } from 'aws-amplify';
2
3async function forgetDevice() {
4 try {
5 await Auth.forgetDevice();
6 } catch (error) {
7 console.log('Error forgetting device', error);
8 }
9}

Fetch devices

You can fetch a list of remembered devices by using the following:

1import { Auth } from 'aws-amplify';
2
3async function fetchDevices() {
4 try {
5 const result = await Auth.fetchDevices();
6 console.log(result);
7 } catch (err) {
8 console.log('Error fetching devices', err);
9 }
10}
1import { Auth } from 'aws-amplify';
2
3async function fetchDevices() {
4 try {
5 const result = await Auth.fetchDevices();
6 console.log(result);
7 } catch (err) {
8 console.log('Error fetching devices', err);
9 }
10}

You can now set up devices to be remembered, forgotten, and fetched.

Conclusion

Congratulations! You finished the Manage MFA settings guide. In this guide, you set up and configured MFA for your users and provided them options on remembering their MFA preferences and devices.

Next steps

Now that you completed setting up multi-factor authentication you may also want to add additional customization. We recommend you learn more about: