Amazon Cognito provides authentication, authorization, and user management for your web and mobile apps. Your users can sign in directly with a username and password, or through a third party such as Facebook, Amazon, Google, or Apple.

We can configure Amazon Cognito in such a way that users can sign in with their email, phone, or user name. If you enable sign-in with a user name, you can set a "preferred user name" attribute (preferred_username) which will work as an alternate value for the username attribute (username).

Table of Content :

The SMS MFA for Cognito user is that, while doing the login to the pool along with the username and password user need to enter code received on mobile via SMS to the API.when the credentials are matched, then only user gets logged in to the Cognito pool and access the required AWS services.

We have the following steps to enable SMS MFA for the Cognito pool.

  • You can only choose MFA as Required when you initially create a user pool.
  • Phone numbers must be verified if MFA is enabled and an SMS text message is chosen as a second factor.
  • Advanced security features require that MFA is enabled, and set as optional in the Amazon Cognito user pool console. For more information, see Adding Advanced Security to a User Pool.


Configuring Multi-Factor Authentication

To configure MFA in the Amazon Cognito console

1). From the left navigation bar, choose MFA and verifications.

2). Choose whether MFA is Off, Optional, or Required.

configure sms mfa cognito user pool


3). Choose Optional to enable MFA on a per-user basis, or if you are using the risk-based adaptive authentication.

4). Your users can use SMS text message or Time-based One-time Password as a second factor. Choose which the second factor to support your app. This allows SMS to be used as a password recovery mechanism which is disjoint from an authentication factor.

5). If you're using SMS text messages as a second factor and you don't have an IAM role defined with this permission, then you can create one in the console. Choose to Create a role to create an IAM role to allow Amazon Cognito to send SMS messages to your users on your behalf.

configure sms mfa role for cognito pool


6). Choose Save changes.

Amazon Cognito can automatically verify email addresses or mobile phone numbers by sending a verification code or, for email, a verification link. For email addresses, the code or link is sent in an email message. For phone numbers, the code is sent in an SMS text message.

Verification of a phone or email is necessary to automatically confirm users and enable recovery from forgotten passwords.

We are using Java SDK for AWS Cognito.so we have

Maven dependency for AWS Cognito Enable SMS MFA

<dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-core</artifactId> <version>1.11.764</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-cognitoidp</artifactId> <version>1.11.764</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk</artifactId> <version>1.11.360</version> </dependency>


We have cognitoClient instance

public static AWSCognitoIdentityProvider getAWSCognitoIdentityClient() { System.setProperty("aws.accessKeyId", "-- your accessKey Id--"); System.setProperty("aws.secretKey", "-- your secret Key--"); AWSCognitoIdentityProvider cognitoClient = AWSCognitoIdentityProviderClientBuilder.standard().withRegion(Regions.AP_SOUTH_1).withCredentials(new SystemPropertiesCredentialsProvider()).build(); return client; }

Set SMS MFA preferences for Cognito user

While SignUp user to Cognito pool we have to call this method, to set MFA preferences of the user as SMS MFA.

public static void registerMFA(String accessToken){ try { AWSCognitoIdentityProvider client = getAWSCognitoIdentityClient(); SMSMfaSettingsType sMSMfaSettings = new SMSMfaSettingsType() .withEnabled(true) .withPreferredMfa(true); SetUserMFAPreferenceRequest setUserMFAPreferenceRequest = new SetUserMFAPreferenceRequest() .withAccessToken(accessToken) .withSMSMfaSettings(sMSMfaSettings); SetUserMFAPreferenceResult result = client.setUserMFAPreference(setUserMFAPreferenceRequest); System.out.println("MFA preference registered successfully"); } catch (Exception e) { e.printStackTrace(); } }

Our request becomes

{ "SMSMfaSettings": { "Enabled": boolean, "PreferredMfa": boolean }, "SoftwareTokenMfaSettings": { "Enabled": boolean, "PreferredMfa": boolean }, "Username": "string", "UserPoolId": "string" }


Sign In user to the Cognito pool

public static InitiateAuthResult signInUser(String username,String password) { try { AWSCognitoIdentityProvider client = getAWSCognitoIdentityClient(); final Map<String, String> authParams = new HashMap<String, String>(); authParams.put("USERNAME", username); authParams.put("PASSWORD", password); final InitiateAuthRequest initiateAuthRequest = new InitiateAuthRequest() .withClientId(clientId) .withAuthFlow(AuthFlowType.USER_PASSWORD_AUTH) .withAuthParameters(authParams); final InitiateAuthResult result = client.initiateAuth(initiateAuthRequest); System.out.println("Result Challange is : " + result.getChallengeName()); return result; } catch (Exception e) { e.printStackTrace(); } return null; }

If the above code executed in the time of signUp user.

When user tries to login using the following code we get InitiateAuthResult.In that we get result.getChallengeName() as "SMS_MFA". If it is so.our SMS MFA is activated. The SMS code will be sent to the registered mobile number of the user.

Then the user needs to enter the MFA code received on mobile, username, and session of the previous API call to the below method.

public static AuthenticationResultType mfaLogin(String username, String mfaCode, String session) { AWSCognitoIdentityProvider client = getAWSCognitoIdentityClient(); Map<String, String> challengeResponses = new HashMap<String, String>(); challengeResponses.put("USERNAME", username); challengeResponses.put("SMS_MFA_CODE", mfa_code); RespondToAuthChallengeRequest respondToAuthChallengeRequest = new RespondToAuthChallengeRequest() .withChallengeName(ChallengeNameType.SMS_MFA).withClientId(clientId) .withChallengeResponses(challengeResponses).withSession(session); RespondToAuthChallengeResult respondToAuthChallengeResult = client.respondToAuthChallenge(respondToAuthChallengeRequest); System.out.println("User logged in Cognito user pool using SMS MFA."); return respondToAuthChallengeResult.getAuthenticationResult(); }

If authentication is successful then the result is returned to the user. In that we have an access token, using which users can access AWS services.

In this article, we have seen AWS Cognito Enable SMS MFA Using Java. All source code in the article can be found in the GitHub repository.