Closed dkliss closed 7 months ago
Hi @dkliss, good question, the observed behavior is expected when using Amplify.Auth.verifyTotpSetup()
.
The correct API to call while onboarding a User to MFA is Amplify.Auth.confirmSignIn(confirmationValue: totpCode)
.
If the code is wrong, a CodeMismatchException
will be thrown allowing you to try again with no need to call verifyTotpSetup()
. After a valid code, the user will be signed in.
We have a command line example app with this implementation found on our github.
Hi @dkliss, good question, the observed behavior is expected when using
Amplify.Auth.verifyTotpSetup()
.The correct API to call while onboarding a User to MFA is
Amplify.Auth.confirmSignIn(confirmationValue: totpCode)
.If the code is wrong, a
CodeMismatchException
will be thrown allowing you to try again with no need to callverifyTotpSetup()
. After a valid code, the user will be signed in.We have a command line example app with this implementation found on our github.
Thanks @Equartey for confirming this is as expected.
As a user when I go through the QR setup process, what is happening is, if i enter incorrect code for Amplify.Auth.verifyTotpSetup(totpCode), then I cannot retry after ONE attempt. The only way i can re-verify is to re-generate QR code, re-do scan and then re-run verify code & that from user perspective seems a lot.
What I was expecting is that a user have option to EITHER retry verify OR if only verifyTotpSetup(totpCode) is expected and setUpTotp() has been run, a user is always taken to verifyTotpSetup(totpCode) and not asked to re-run setUpTotp() and repeat all process (including re-scan with Authenticator).
I am not adding TOTP at Sign In. But allowing user to update/enable TOTP ONLY after a user has Signed In i.e. this API Amplify.Auth.confirmSignIn(confirmationValue) is not available to me unless I log out and login again after setUpTotp() and verifyTotpSetup(totpCode) are complete.
The Amplify.Auth.confirmSignIn(confirmationValue) works as expected i.e. it does allow multiple attempts. I only have issue with verifyTotpSetup(totpCode) , which restrict a user to single attempt else re-do all scan-sync process.
If a user see verifyTotpSetup() with an exception, it may be perceived as TOTP not setup and user will need to repeat process esp if verifyTotpSetup() is mandatory Or is this step Optional?
Hi @dkliss, I looked into it further and it does actually appear to be a bug. Thank you for the extra context with your use case as it helped narrow down the issue.
I'm working on addressing it and will update you here when I can.
Hi @dkliss, I looked into it further and it does actually appear to be a bug. Thank you for the extra context with your use case as it helped narrow down the issue.
I'm working on addressing it and will update you here when I can.
Thanks @Equartey. I will wait for update to retest.
Hi @dkliss this has been fixed in amplify_auth_cognito: ^1.7.1
.
I'm going to close this issue as complete, please reach out if you encounter another issue.
Hi @Equartey, thanks for the update.
I tried below but I received no exception such as "Code Mismatch" when I enter any incorrect code.
With correct code, TOTP is setup as expected.
amplify_flutter: ^1.7.0
amplify_auth_cognito: ^1.7.1
Flutter 3.19.3
Test Platform: Android & iOS Emulators.
What I did:
Hi @dkliss, we catch the exception internally, but allow multiple calls to verifyTotpSetup
without the need to restart setup.
I suspect the problem you're facing is not receiving enough feedback during the code verification process. Basically, how would you determine if the attempt was successful or a failure requiring a retry. Which is understandably frustrating.
Can you confirm you're able to submit multiple calls to verifyTotpSetup
when passing an incorrect code without having to restart setup (your steps 1-3)?
Try:
Amplify.Auth.setUpTotp()
Amplify.Auth.verifyTotpSetup(INVALID_CODE)
(can be repeated) -- note: no exception thrownAmplify.Auth.verifyTotpSetup(VALID_CODE)
Meanwhile, we will investigate how to provide better feedback to you.
Hi @dkliss, I have a work around for you in the meantime.
When setting up a user's TOTP for the first time, you can check the user's MFA preference to see if TOTP is enabled. Now this will only be of value during initial setup on the first device as it only checks to see if TOTP is enabled for the user not, if the current attempt was successful.
final plugin = Amplify.Auth.getPlugin(AmplifyAuthCognito.pluginKey);
final response = await plugin.fetchMfaPreference();
print(response);
// TOTP not enabled
// UserMfaPreference {
// "enabled": [],
// "preferred": null
// }
// TOTP enabled
// UserMfaPreference {
// "enabled": [
// "TOTP" // Can check if this exists to determine if setup was successful
// ],
// "preferred": "TOTP"
// }
Not a perfect fix, but hopefully unblocks you while we investigate a better solution.
Hi @dkliss, we catch the exception internally, but allow multiple calls to
verifyTotpSetup
without the need to restart setup.I suspect the problem you're facing is not receiving enough feedback during the code verification process. Basically, how would you determine if the attempt was successful or a failure requiring a retry. Which is understandably frustrating.
Can you confirm you're able to submit multiple calls to
verifyTotpSetup
when passing an incorrect code without having to restart setup (your steps 1-3)?Try:
- call
Amplify.Auth.setUpTotp()
- call
Amplify.Auth.verifyTotpSetup(INVALID_CODE)
(can be repeated) -- note: no exception thrown- call
Amplify.Auth.verifyTotpSetup(VALID_CODE)
- Successful setup
Meanwhile, we will investigate how to provide better feedback to you.
Hi @Equartey , thanks for the response.
I can confirm multiple attempts works as expected. I tried 5 or 6 attempts and did not received "There is no active TOTP setup" issue anymore.
CodeMismatchException will be useful so a user can be redirected correctly based on if a user enters correct or incorrect code.
I will wait for this update.
Hi @dkliss, I have a work around for you in the meantime.
When setting up a user's TOTP for the first time, you can check the user's MFA preference to see if TOTP is enabled. Now this will only be of value during initial setup on the first device as it only checks to see if TOTP is enabled for the user not, if the current attempt was successful.
final plugin = Amplify.Auth.getPlugin(AmplifyAuthCognito.pluginKey); final response = await plugin.fetchMfaPreference(); print(response); // TOTP not enabled // UserMfaPreference { // "enabled": [], // "preferred": null // } // TOTP enabled // UserMfaPreference { // "enabled": [ // "TOTP" // Can check if this exists to determine if setup was successful // ], // "preferred": "TOTP" // }
Not a perfect fix, but hopefully unblocks you while we investigate a better solution.
Thanks @Equartey for the proposed workaround.
I tested the workaround and I can handle failed entry this way for now for first Authenticator ONLY (as you mentioned).
However, (as you indicated) when I generate a new QR code for second Authenticator, this approach does not work because mfasList received from fetchMfaPreference() already have a TOTP enabled (because of the first Authenticator).
CodeMismatchException per uniquely generated QR code secret is important (I think), else this will not work properly. And this may tie into how do we track all secrets or QRs (i.e. Authenticators) generated & which of those are verified and which of those are not. I.e. fetchMfaPreference() should send a list of all active/inactive TOTPs.
I decided to not use this workaround for now as this does not seem to solve the problem completely and may generate false positives. I will wait for an update on this to retest.
UPDATE: I decided to re-implement the workaround with a (client side) Limitation of one Authenticator allowed per user". I.e. a user will ONLY be able to to setup a maximum of one Authenticator app. This is because, single Authenticator setup and verify (with proposed workaround) works as expected.
Once an update is received on how to handle multiple separate Authenticators to verifyTotp as well as enable/disable, I will retest that.
Hi @dkliss, I appreciate the discussion so far. It's been helpful for me to understand your use case. I've opened https://github.com/aws-amplify/amplify-flutter/pull/4558 to throw an exception during TOTP setup. Will update you when it's released.
I believe your updated approach, limiting users to one Authenticator device, improves the user experience until we can handle multiple TOTP secrets properly. Which we will continue to track in the other issue you've opened, https://github.com/aws-amplify/amplify-flutter/issues/4509.
Hi @dkliss, we ended up reverting 1.7.1 as it broke existing behavior, but we have released the idle fix. Please consume amplify_auth_cognito: ^1.7.2
.
Amplify.Auth.verifyTotpSetup(INVALID_CODE)
now throws an EnableSoftwareTokenMfaException
and allows retries without restarting the setup process.
Again, thank you for bringing this to our attention. I'm going to close this, but please reach out if you have any issues.
Hi @Equartey Thanks you for response.
I verified this and I received exception as expected. Much appreciate your help on this throughout.
Description
-EDIT, Correction on sync
Hi,
When setting up TOTP, after Amplify.Auth.setUpTotp() has been setup, we will be at Amplify.Auth.verifyTotpSetup(totpCode). The verifyTotpSetup() only allows single attempt to enter correct code. And if second attempt is made I get below exception. Is this how it is expected to work (i.e. only one attempt)?
To reproduce:
In above scenario, even if I do not remove (i.e. execute step 6) authenticator scanned in step 2 above (Connect with Authenticator), Amplify.Auth.verifyTotpSetup() still works even after a new Amplify.Auth.setUpTotp() is generated in step 5.
To reproduce (Step 6 removed from above scenario):
Whats happening in this seems like old QR code is still in Amplify and hence when I add verify code, that one is used.
Categories
Steps to Reproduce
No response
Screenshots
No response
Platforms
Flutter Version
3.19.1
Amplify Flutter Version
1.6.1
Deployment Method
Amplify CLI
Schema
No response