Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(auth): TOTP MFA #3146

Merged
merged 7 commits into from
Aug 24, 2023
Merged

feat(auth): TOTP MFA #3146

merged 7 commits into from
Aug 24, 2023

Conversation

dnys1
Copy link
Contributor

@dnys1 dnys1 commented Jun 5, 2023

  • Implements TOTP MFA as part of the signIn flow.
  • Adds category methods for setting up TOTP outside the signIn flow.
  • Adds plugin methods for getting/setting the user's MFA preferences at any time.

@dnys1 dnys1 force-pushed the feat/auth/totp branch 5 times, most recently from 8d6f87b to 282b1c0 Compare June 14, 2023 20:43
@Kaspear
Copy link

Kaspear commented Jun 19, 2023

@dnys1 Thanks for taking care of this! When do you think this feature will be released?

@dnys1
Copy link
Contributor Author

dnys1 commented Jun 21, 2023

@Kaspear I don't have any firm timeframe yet, but it is one of our highest priority issues!

@dnys1 dnys1 marked this pull request as ready for review June 23, 2023 19:05
@dnys1 dnys1 requested a review from a team as a code owner June 23, 2023 19:05
@dnys1 dnys1 force-pushed the feat/auth/totp branch 2 times, most recently from 80ba8b4 to 76c343b Compare June 23, 2023 19:27
Copy link
Member

@Equartey Equartey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally crushed this one. I've been using this branch for the past couple weeks and it's worked great 🎉

Still needing to test the multiple MFA selection workflow, but here's some feedback in the meantime 😁

packages/amplify_core/lib/src/types/auth/auth_types.dart Outdated Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love all these test 🎉

Can we make this test file more digestible and easier to maintain? Maybe consider adding contextual comments to each scenario or breaking it up into two at least two files based on the testRunners. Either case I think would help provide better maintainer DX imo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've split the tests into multiple files. I've tried to leave rationale for many of the expectations. Given they all follow the same pattern (lots of copy/paste between the tests), I think grokking one test makes the rest simple to understand.

@mikolaj1982
Copy link

that looks great! I also sit for last couple of week on branch feat/auth/totp and seem like totp with authenticator app is all working so can't wait for release. Thank you for your hard work @dnys1

@dnys1 dnys1 force-pushed the feat/auth/totp branch 2 times, most recently from c19fd2e to d06e6b0 Compare July 7, 2023 19:43
Jordan-Nelson
Jordan-Nelson previously approved these changes Jul 7, 2023
Comment on lines 16 to 19
const UserMfaPreference({
Set<MfaType>? enabled,
this.preferred,
}) : enabled = enabled ?? const {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I am missing something. Why not:

const UserMfaPreference({
  this.enabled = const {},
  this.preferred,
});

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wanting passing null before because it makes things like list?.map(...).toSet() cleaner if I don't have to duplicate ?? const {} everywhere. But I changed it since I'm not doing that any more.


@override
Map<String, Object?> toJson() => {
'enabled': enabled.map((typ) => typ.name.toUpperCase()).toList(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this supposed to be type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either way. Updated to type.

/// Initiates setup of a time-based one-time passcode (TOTP) MFA method for the
/// current user.
///
/// Your backend must be set up with TOTP MFA enabled prior to calling this method.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What exception is thrown if the back end isn't set up for totp mfa?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SoftwareTokenMFANotFoundException

String? accountName,
}) =>
Uri(
scheme: 'otpauth',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This scheme is used by all authenticator apps (or, at least all popular ones - MS, Google, Authy, Last Pass, etc.)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, while there isn't a formal specification for otp URIs, this is the commonly used schema. The popular apps recognize this schema, this is made clear by their apps opening via native platform API calls with this schema. Which is exactly what we are doing in our Authenticator TOTP work.

Equartey
Equartey previously approved these changes Jul 10, 2023
@dnys1 dnys1 dismissed stale reviews from Equartey and Jordan-Nelson via 403c387 July 10, 2023 18:49
Copy link
Member

@Equartey Equartey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline. Here is my fix for the infra script failures

infra/lib/auth/stack.create-user.ts Outdated Show resolved Hide resolved
infra/lib/auth/stack.create-user.ts Outdated Show resolved Hide resolved
@dnys1 dnys1 added the pr:squash PR should be submitted with a sqaush commit label Jul 20, 2023
@dnys1 dnys1 requested a review from Equartey July 20, 2023 17:56
@luigi198
Copy link

luigi198 commented Jul 27, 2023

Hi, we are deciding if we are going to use Amplify - Flutter and MFA with TOTP is a requirement, do you guys have an ETA for this feature to be deployed? if not I think we will not be able to use Amplify for our project. thanks!
@dnys1

@abdallahshaban557
Copy link
Contributor

Hi @luigi198 - we are getting really close to shipping this, we are doing our internal rounds of reviews. When would you like this to be available by?

@luigi198
Copy link

@abdallahshaban557 We are working on a PoC to prove we can use this tech, we will be implementing MFA probably in September, we noticed you guys deployed a new version today, that's a good sign for my boss, if I can get a written confirmation MFA TOTP will be supported for September (we are flexible with the month, we can work on other features meanwhile), we are probably good to go

@abdallahshaban557
Copy link
Contributor

Hi @luigi198 - we should have it ready by then. Thank you for letting us know!

Dillon Nys added 6 commits August 21, 2023 08:12
Expands E2E backends for all TOTP/SMS MFA combinations.
Fix casing when mapping SDK exceptions.
Adds TOTP MFA support to the `signIn` and `confirmSignIn` flows and adds two new methods to the Cognito plugin for fetching and updating the user's MFA preferences: `fetchMfaPreference` and `updateMfaPreference`.
Adds E2E tests for TOTP MFA and splits existing MFA tests by backend configuration: SMS, TOTP, and SMS/TOTP.
@@ -199,6 +215,23 @@ Future<void> confirmMfaUser(String mfaCode) async {
}
// #enddocregion confirm-signin

// #docregion handle-mfa-selection
Future<MfaType> _promptUserPreference(Set<MfaType> allowedTypes) async {
throw UnimplementedError();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be implemented?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in favor of // ...

@@ -155,7 +155,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1300;
LastUpgradeCheck = 1430;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Been seeing this change locally. Does this typically get committed? If so, what's the significance?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it should be committed. Flutter and Xcode updates can modify the project settings.

Comment on lines 1304 to 1307
/// The [TotpSetupDetails] returned contains a [TotpSetupDetails.getSetupUri]
/// method which can be used to display a QR code or render a button to open
/// the user's installed authenticator app. After setup is complete on the user's
/// end, call [verifyTotpSetup] with a one-time code to complete registration.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might reword this section to make it clear TotpSetupDetails.getSetupUri return's the URI. Right now it reads like it shows the relevant QR code.

Suggested change
/// The [TotpSetupDetails] returned contains a [TotpSetupDetails.getSetupUri]
/// method which can be used to display a QR code or render a button to open
/// the user's installed authenticator app. After setup is complete on the user's
/// end, call [verifyTotpSetup] with a one-time code to complete registration.
/// The [TotpSetupDetails] returned contains a [TotpSetupDetails.getSetupUri]
/// method for retrieving the setup URI. Which can be used to build a QR code or
/// a button to open the user's installed authenticator app. After setup is complete
/// on the user's end, call [verifyTotpSetup] with a one-time code to complete registration.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done 👍

@dnys1 dnys1 merged commit 4d50bb1 into main Aug 24, 2023
192 of 207 checks passed
@dnys1 dnys1 deleted the feat/auth/totp branch August 24, 2023 19:09
@abdallahshaban557
Copy link
Contributor

@Kaspear @mikolaj1982 @luigi198 - Just wanted to make sure you are aware that this feature has now been launched! It is available from the Amplify Flutter library and the Authenticator UI component.

@billnice250
Copy link

@dnys1
Thanks a lot for your effort!
Already integrated it in my app yesterday and everything is working smoothly!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pr:squash PR should be submitted with a sqaush commit
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants