diff --git a/src/fragments/lib/auth/android/signin_next_steps/91_confirm_totp_mfa.mdx b/src/fragments/lib/auth/android/signin_next_steps/91_confirm_totp_mfa.mdx
deleted file mode 100644
index a21cb2b6a62..00000000000
--- a/src/fragments/lib/auth/android/signin_next_steps/91_confirm_totp_mfa.mdx
+++ /dev/null
@@ -1,91 +0,0 @@
-If the next step is `CONFIRM_SIGN_IN_WITH_TOTP_CODE`, Amplify Auth is waiting for the user to enter their TOTP code. To handle this step, your app's UI must prompt the user to enter the code. After the user enters the code, your implementation must pass the value to Amplify Auth `confirmSignIn` API.
-
-Note: the signIn result also includes an `AuthCodeDeliveryDetails` member. It includes additional information about the code delivery.
-
-
-
-
-
-```java
-Amplify.Auth.confirmSignIn(
- "TOTP confirmation code",
- result -> {
- if (result.isSignedIn()) {
- Log.i("AuthQuickstart", "Confirm signIn succeeded");
- } else {
- Log.i("AuthQuickstart", "Confirm sign in not complete. There might be additional steps: " + result.getNextStep());
- // Switch on the next step to take appropriate actions.
- // If `signInResult.isSignedIn` is true, the next step
- // is 'done', and the user is now signed in.
- }
- },
- error -> Log.e("AuthQuickstart", "Confirm sign in failed: " + error)
-);
-```
-
-
-
-
-```kotlin
-Amplify.Auth.confirmSignIn(
- "TOTP confirmation code",
- { result ->
- if (result.isSignedIn) {
- Log.i("AuthQuickstart", "Confirm signIn succeeded")
- } else {
- Log.i(
- "AuthQuickstart",
- "Confirm sign in not complete. There might be additional steps: ${result.nextStep}"
- )
- // Switch on the next step to take appropriate actions.
- // If `signInResult.isSignedIn` is true, the next step
- // is 'done', and the user is now signed in.
- }
- },
- { error -> Log.e("AuthQuickstart", "Confirm sign in failed: $error") }
-)
-```
-
-
-
-
-```kotlin
-try {
- val result = Amplify.Auth.confirmSignIn(
- "confirmation code"
- )
- if (result.isSignedIn) {
- Log.i("AuthQuickstart", "Confirm signIn succeeded")
- } else {
- Log.i("AuthQuickstart", "Confirm sign in not complete. There might be additional steps: ${result.nextStep}")
- // Switch on the next step to take appropriate actions.
- // If `signInResult.isSignedIn` is true, the next step
- // is 'done', and the user is now signed in.
- }
-} catch (error: Exception) {
- Log.e("AuthQuickstart", "Unexpected error: $error")
-}
-```
-
-
-
-
-```java
-RxAmplify.Auth.confirmSignIn(
- "TOTP confirmation code").subscribe(
- result -> {
- if (result.isSignedIn()) {
- Log.i("AuthQuickstart", "Confirm signIn succeeded");
- } else {
- Log.i("AuthQuickstart", "Confirm sign in not complete. There might be additional steps: " + result.getNextStep());
- // Switch on the next step to take appropriate actions.
- // If `signInResult.isSignedIn` is true, the next step
- // is 'done', and the user is now signed in.
- }
- },
- error -> Log.e("AuthQuickstart", "Confirm sign in failed: " + error)
- );
-```
-
-
-
diff --git a/src/fragments/lib/auth/common/mfa/flows.mdx b/src/fragments/lib/auth/common/mfa/flows.mdx
index 441a69f1f88..f73693a9644 100644
--- a/src/fragments/lib/auth/common/mfa/flows.mdx
+++ b/src/fragments/lib/auth/common/mfa/flows.mdx
@@ -219,13 +219,23 @@ You can use Time-based One-Time Password (TOTP) for multi-factor authentication
### Setting up TOTP for a user
+
+After you initiate a user sign in with the `signIn` API where a user is required to set up TOTP as an MFA method, the API call will return `CONTINUE_SIGN_IN_WITH_TOTP_SETUP` as a challenge and next step to handle in your app. You will get that challenge if the following conditions are met:
+
+
After you initiate a user sign in with the `signIn` API where a user is required to set up TOTP as an MFA method, the API call will return `continueSignInWithTOTPSetup` 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
- User does not have TOTP MFA set up already.
+
+The `CONTINUE_SIGN_IN_WITH_TOTP_SETUP` step signifies that the user must set up TOTP before they can sign in. The step returns an associated value of type `TOTPSetupDetails` which must be used to configure an authenticator app like Microsoft Authenticator or Google Authenticator. `TOTPSetupDetails` provides a helper method called `getSetupURI` which generates a URI that can be used, for example, in a button to open the user's installed authenticator app. For more advanced use cases, `TOTPSetupDetails` also contains a `sharedSecret` which can be used to either generate a QR code or be manually entered into an authenticator app.
+
+
The `continueSignInWithTOTPSetup` step signifies that the user must set up TOTP before they can sign in. The step returns an associated value of type `TOTPSetupDetails` which must be used to configure an authenticator app like Microsoft Authenticator or Google Authenticator. `TOTPSetupDetails` provides a helper method called `getSetupURI` which generates a URI that can be used, for example, in a button to open the user's installed authenticator app. For more advanced use cases, `TOTPSetupDetails` also contains a `sharedSecret` 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 can generate a TOTP code and provide it to the library to complete the sign in process.
@@ -599,15 +609,87 @@ Future updateMfaPreferences() async {
+
+If multiple MFA methods are enabled for the user, the `signIn` API will return `CONTINUE_SIGN_IN_WITH_MFA_SELECTION` as the next step in the auth flow. During this scenario, the user should be prompted to select the MFA method they want to use to sign in and their preference should be passed to `confirmSignIn`.
+
+
If multiple MFA methods are enabled for the user, the `signIn` API will return `continueSignInWithMFASelection` as the next step in the auth flow. During this scenario, the user should be prompted to select the MFA method they want to use to sign in and their preference should be passed to `confirmSignIn`.
+
import iosContinueSignInWithMFASelection from '/src/fragments/lib/auth/ios/signin_next_steps/91_continue_mfa_selection_code.mdx';
-import androidContinueSignInWithMFASelection from '/src/fragments/lib/auth/android/signin_next_steps/91_confirm_totp_mfa.mdx';
+
+
+
+
+
+```java
+Amplify.Auth.confirmSignIn(
+ MFATypeUtil.getChallengeResponse(MFAType.TOTP),
+ result -> {
+ if (result.getNextStep().getSignInStep() == AuthSignInStep.CONFIRM_SIGN_IN_WITH_TOTP_CODE) {
+ Log.i("AuthQuickStart", "Received next step as confirm sign in with TOTP");
+ }
+ // ...
+ },
+ error -> Log.e("AuthQuickstart", "Confirm sign in failed: " + error)
+);
+```
+
+
+
+
+```kotlin
+Amplify.Auth.confirmSignIn(
+ MFAType.TOTP.challengeResponse,
+ { result ->
+ if (result.nextStep.signInStep == AuthSignInStep.CONFIRM_SIGN_IN_WITH_TOTP_CODE) {
+ Log.i("AuthQuickStart", "Received next step as confirm sign in with TOTP");
+ }
+ // ...
+ },
+ { error -> Log.e("AuthQuickstart", "Confirm sign in failed: $error") }
+)
+```
+
+
+
+
+```kotlin
+try {
+ val result = Amplify.Auth.confirmSignIn(MFAType.TOTP.challengeResponse)
+ if (result.nextStep.signInStep == AuthSignInStep.CONFIRM_SIGN_IN_WITH_TOTP_CODE) {
+ Log.i("AuthQuickStart", "Received next step as confirm sign in with TOTP");
+ }
+ // ...
+} catch(error: Exception) {
+ Log.e("AuthQuickstart", "Confirm sign in failed: $error")
+}
+```
-
+
+
+
+```java
+RxAmplify.Auth.confirmSignIn(
+ MFATypeUtil.getChallengeResponse(MFAType.TOTP)
+).subscribe(
+ result -> {
+ if (result.getNextStep().getSignInStep() == AuthSignInStep.CONFIRM_SIGN_IN_WITH_TOTP_CODE) {
+ Log.i("AuthQuickStart", "Received next step as confirm sign in with TOTP");
+ }
+ // ...
+ },
+ error -> Log.e("AuthQuickstart", "Confirm sign in failed: " + error)
+);
+```
+
+
+
+
+
diff --git a/src/fragments/lib/auth/native_common/signin_next_steps/common.mdx b/src/fragments/lib/auth/native_common/signin_next_steps/common.mdx
index 8366f29a069..8c615f36156 100644
--- a/src/fragments/lib/auth/native_common/signin_next_steps/common.mdx
+++ b/src/fragments/lib/auth/native_common/signin_next_steps/common.mdx
@@ -35,7 +35,12 @@ import flutter1 from '/src/fragments/lib/auth/flutter/signin_next_steps/20_confi
### Confirm signin with TOTP MFA
+
+If the next step is `CONFIRM_SIGN_IN_WITH_TOTP_CODE`, you should prompt the user to enter the TOTP code from their associated authenticator app during set up. The code is a six-digit number that changes every 30 seconds. The user must enter the code before the 30-second window expires.
+
+
If the next step is `confirmSignInWithTOTPCode`, you should prompt the user to enter the TOTP code from their associated authenticator app during set up. The code is a six-digit number that changes every 30 seconds. The user must enter the code before the 30-second window expires.
+
After the user enters the code, your implementation must pass the value to Amplify Auth `confirmSignIn` API.
@@ -43,6 +48,97 @@ import iosConfirmSignInTotpMFA from '/src/fragments/lib/auth/ios/signin_next_ste
+
+
+
+
+
+```java
+Amplify.Auth.confirmSignIn(
+ "TOTP confirmation code",
+ result -> {
+ if (result.isSignedIn()) {
+ Log.i("AuthQuickstart", "Confirm signIn succeeded");
+ } else {
+ Log.i("AuthQuickstart", "Confirm sign in not complete. There might be additional steps: " + result.getNextStep());
+ // Switch on the next step to take appropriate actions.
+ // If `signInResult.isSignedIn` is true, the next step
+ // is 'done', and the user is now signed in.
+ }
+ },
+ error -> Log.e("AuthQuickstart", "Confirm sign in failed: " + error)
+);
+```
+
+
+
+
+```kotlin
+Amplify.Auth.confirmSignIn(
+ "TOTP confirmation code",
+ { result ->
+ if (result.isSignedIn) {
+ Log.i("AuthQuickstart", "Confirm signIn succeeded")
+ } else {
+ Log.i(
+ "AuthQuickstart",
+ "Confirm sign in not complete. There might be additional steps: ${result.nextStep}"
+ )
+ // Switch on the next step to take appropriate actions.
+ // If `signInResult.isSignedIn` is true, the next step
+ // is 'done', and the user is now signed in.
+ }
+ },
+ { error -> Log.e("AuthQuickstart", "Confirm sign in failed: $error") }
+)
+```
+
+
+
+
+```kotlin
+try {
+ val result = Amplify.Auth.confirmSignIn(
+ "TOTP confirmation code"
+ )
+ if (result.isSignedIn) {
+ Log.i("AuthQuickstart", "Confirm signIn succeeded")
+ } else {
+ Log.i("AuthQuickstart", "Confirm sign in not complete. There might be additional steps: ${result.nextStep}")
+ // Switch on the next step to take appropriate actions.
+ // If `signInResult.isSignedIn` is true, the next step
+ // is 'done', and the user is now signed in.
+ }
+} catch (error: Exception) {
+ Log.e("AuthQuickstart", "Unexpected error: $error")
+}
+```
+
+
+
+
+```java
+RxAmplify.Auth.confirmSignIn(
+ "TOTP confirmation code"
+).subscribe(
+ result -> {
+ if (result.isSignedIn()) {
+ Log.i("AuthQuickstart", "Confirm signIn succeeded");
+ } else {
+ Log.i("AuthQuickstart", "Confirm sign in not complete. There might be additional steps: " + result.getNextStep());
+ // Switch on the next step to take appropriate actions.
+ // If `signInResult.isSignedIn` is true, the next step
+ // is 'done', and the user is now signed in.
+ }
+ },
+ error -> Log.e("AuthQuickstart", "Confirm sign in failed: " + error)
+);
+```
+
+
+
+
+
```dart
@@ -73,12 +169,88 @@ Future confirmTotpUser(String totpCode) async {
### Continue signin with MFA Selection
+
+If the next step is `CONTINUE_SIGN_IN_WITH_MFA_SELECTION`, the user must select the MFA method to use. Amplify Auth currently only supports SMS and TOTP as MFA methods. After the user selects an MFA method, your implementation must pass the selected MFA method to Amplify Auth using `confirmSignIn` API.
+
+
If the next step is `continueSignInWithMFASelection`, the user must select the MFA method to use. Amplify Auth currently only supports SMS and TOTP as MFA methods. After the user selects an MFA method, your implementation must pass the selected MFA method to Amplify Auth using `confirmSignIn` API.
+
import iosContinueSignInWithMFASelectionCode from 'src/fragments/lib/auth/ios/signin_next_steps/91_continue_mfa_selection_code.mdx';
+
+
+
+
+
+```java
+Amplify.Auth.confirmSignIn(
+ MFATypeUtil.getChallengeResponse(MFAType.TOTP),
+ result -> {
+ if (result.getNextStep().getSignInStep() == AuthSignInStep.CONFIRM_SIGN_IN_WITH_TOTP_CODE) {
+ Log.i("AuthQuickStart", "Received next step as confirm sign in with TOTP");
+ }
+ // ...
+ },
+ error -> Log.e("AuthQuickstart", "Confirm sign in failed: " + error)
+);
+```
+
+
+
+
+```kotlin
+Amplify.Auth.confirmSignIn(
+ MFAType.TOTP.challengeResponse,
+ { result ->
+ if (result.nextStep.signInStep == AuthSignInStep.CONFIRM_SIGN_IN_WITH_TOTP_CODE) {
+ Log.i("AuthQuickStart", "Received next step as confirm sign in with TOTP");
+ }
+ // ...
+ },
+ { error -> Log.e("AuthQuickstart", "Confirm sign in failed: $error") }
+)
+```
+
+
+
+
+```kotlin
+try {
+ val result = Amplify.Auth.confirmSignIn(MFAType.TOTP.challengeResponse)
+ if (result.nextStep.signInStep == AuthSignInStep.CONFIRM_SIGN_IN_WITH_TOTP_CODE) {
+ Log.i("AuthQuickStart", "Received next step as confirm sign in with TOTP");
+ }
+ // ...
+} catch(error: Exception) {
+ Log.e("AuthQuickstart", "Confirm sign in failed: $error")
+}
+```
+
+
+
+
+```java
+RxAmplify.Auth.confirmSignIn(
+ MFATypeUtil.getChallengeResponse(MFAType.TOTP)
+).subscribe(
+ result -> {
+ if (result.getNextStep().getSignInStep() == AuthSignInStep.CONFIRM_SIGN_IN_WITH_TOTP_CODE) {
+ Log.i("AuthQuickStart", "Received next step as confirm sign in with TOTP");
+ }
+ // ...
+ },
+ error -> Log.e("AuthQuickstart", "Confirm sign in failed: " + error)
+);
+```
+
+
+
+
+
+
The MFA types which are currently supported by Amplify Auth are:
@@ -118,7 +290,12 @@ Future _handleMfaSelection(MfaType selection) async {
### Continue signin with TOTP Setup
+
+If the next step is `CONTINUE_SIGN_IN_WITH_TOTP_SETUP`, then the user must provide a TOTP code to complete the sign in process. The step returns an associated value of type `TOTPSetupDetails` which would be used for generating TOTP. `TOTPSetupDetails` provides a helper method called `getSetupURI` that can be used to generate a URI, which can be used by native password managers for TOTP association. For example. if the URI is used on Apple platforms, it will trigger the platform's native password manager to associate TOTP with the account. For more advanced use cases, `TOTPSetupDetails` also contains the `sharedSecret` that will be used to either generate a QR code or can be manually entered into an authenticator app.
+
+
If the next step is `continueSignInWithTOTPSetup`, then the user must provide a TOTP code to complete the sign in process. The step returns an associated value of type `TOTPSetupDetails` which would be used for generating TOTP. `TOTPSetupDetails` provides a helper method called `getSetupURI` that can be used to generate a URI, which can be used by native password managers for TOTP association. For example. if the URI is used on Apple platforms, it will trigger the platform's native password manager to associate TOTP with the account. For more advanced use cases, `TOTPSetupDetails` also contains the `sharedSecret` that will be used to either generate a QR code or can be manually entered into an authenticator app.
+
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.
@@ -126,6 +303,149 @@ import iosContinueSignInWithMFASetup from 'src/fragments/lib/auth/ios/signin_nex
+
+
+
+
+
+```java
+
+void handleSignInResult(AuthSignInResult result) {
+ switch(result.getNextStep().getSignInStep()) {
+ // ...
+ case CONTINUE_SIGN_IN_WITH_TOTP_SETUP:
+ final TOTPSetupDetails totpSetupDetails = result.getNextStep().getTotpSetupDetails();
+ final Uri setupUri = totpSetupDetails.getSetupURI("MyAppName");
+ Log.i("AuthQuickStart", "Open URI to complete setup: " + setupUri);
+ break;
+ }
+}
+
+// Then, pass the TOTP code to `confirmSignIn`
+
+Amplify.Auth.confirmSignIn(
+ totpCodeFromAuthenticatorApp,
+ result -> {
+ if (result.isSignedIn()) {
+ Log.i("AuthQuickstart", "Confirm signIn succeeded");
+ } else {
+ Log.i("AuthQuickstart", "Confirm sign in not complete. There might be additional steps: " + result.getNextStep());
+ // Switch on the next step to take appropriate actions.
+ // If `signInResult.isSignedIn` is true, the next step
+ // is 'done', and the user is now signed in.
+ }
+ },
+ error -> Log.e("AuthQuickstart", "Confirm sign in failed: " + error)
+);
+```
+
+
+
+
+```kotlin
+
+fun handleSignInResult(result: AuthSignInResult) {
+ when (result.nextStep.signInStep) {
+ // ...
+ AuthSignInStep.CONTINUE_SIGN_IN_WITH_TOTP_SETUP -> {
+ val totpSetupDetails = result.nextStep.totpSetupDetails
+ val setupUri = totpSetupDetails!!.getSetupURI("MyAppName")
+ Log.i("AuthQuickStart", "Open URI to complete setup: $setupUri")
+ }
+ }
+}
+
+// Then, pass the TOTP code to `confirmSignIn`
+
+Amplify.Auth.confirmSignIn(
+ totpCodeFromAuthenticatorApp,
+ { result ->
+ if (result.isSignedIn) {
+ Log.i("AuthQuickstart", "Confirm signIn succeeded")
+ } else {
+ Log.i("AuthQuickstart", "Confirm sign in not complete. There might be additional steps: ${result.nextStep}")
+ // Switch on the next step to take appropriate actions.
+ // If `signInResult.isSignedIn` is true, the next step
+ // is 'done', and the user is now signed in.
+ }
+ },
+ { error -> Log.e("AuthQuickstart", "Confirm sign in failed: $error") }
+)
+```
+
+
+
+
+```kotlin
+
+fun handleSignInResult(result: AuthSignInResult) {
+ when (result.nextStep.signInStep) {
+ // ...
+ AuthSignInStep.CONTINUE_SIGN_IN_WITH_TOTP_SETUP -> {
+ val totpSetupDetails = result.nextStep.totpSetupDetails
+ val setupUri = totpSetupDetails!!.getSetupURI("MyAppName")
+ Log.i("AuthQuickStart", "Open URI to complete setup: $setupUri")
+ }
+ }
+}
+
+// Then, pass the TOTP code to `confirmSignIn`
+
+try {
+ val result = Amplify.Auth.confirmSignIn(totpCodeFromAuthenticatorApp)
+ if (result.isSignedIn) {
+ Log.i("AuthQuickstart", "Confirm signIn succeeded")
+ } else {
+ Log.i("AuthQuickstart", "Confirm sign in not complete. There might be additional steps: ${result.nextStep}")
+ // Switch on the next step to take appropriate actions.
+ // If `signInResult.isSignedIn` is true, the next step
+ // is 'done', and the user is now signed in.
+ }
+} catch(error: Exception) {
+ Log.e("AuthQuickstart", "Confirm sign in failed: $error")
+}
+```
+
+
+
+
+```java
+ void handleSignInResult(AuthSignInResult result) {
+ switch(result.getNextStep().getSignInStep()) {
+ // ...
+ case CONTINUE_SIGN_IN_WITH_TOTP_SETUP:
+ final TOTPSetupDetails totpSetupDetails = result.getNextStep().getTotpSetupDetails();
+ final Uri setupUri = totpSetupDetails.getSetupURI("MyAppName");
+ Log.i("AuthQuickStart", "Open URI to complete setup: " + setupUri);
+ break;
+ }
+ }
+
+
+// Then, pass the TOTP code to `confirmSignIn`
+
+RxAmplify.Auth.confirmSignIn(
+ totpCodeFromAuthenticatorApp
+).subscribe(
+ result -> {
+ if (result.isSignedIn()) {
+ Log.i("AuthQuickstart", "Confirm signIn succeeded");
+ } else {
+ Log.i("AuthQuickstart", "Confirm sign in not complete. There might be additional steps: " + result.getNextStep());
+ // Switch on the next step to take appropriate actions.
+ // If `signInResult.isSignedIn` is true, the next step
+ // is 'done', and the user is now signed in.
+ }
+ },
+ error -> Log.e("AuthQuickstart", "Confirm sign in failed: " + error)
+);
+```
+
+
+
+
+
+
```dart