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

chore(auth): add email otp mfa enums and types #5237

Open
wants to merge 26 commits into
base: feat/email-otp-mfa
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
1b5d2bd
chore: add mfaType enum values,
khatruong2009 Aug 2, 2024
a6492d7
chore: add sign in step enums
khatruong2009 Aug 2, 2024
755f30d
chore: add ChallengeName
khatruong2009 Aug 2, 2024
95f658b
Revert "chore: add ChallengeName"
khatruong2009 Aug 5, 2024
1f72aca
Update packages/amplify_core/lib/src/types/auth/sign_in/auth_sign_in_…
khatruong2009 Aug 6, 2024
a5abb1e
chore add email mfa to sdk_bridge and state machine
khatruong2009 Sep 10, 2024
edaf999
chore: add email mfa to constants.dart
khatruong2009 Sep 10, 2024
630adad
chore: add email to updateMfaPreference API
khatruong2009 Sep 10, 2024
3f4efce
chore: generate code for mfa types/methods and sign in step
khatruong2009 Sep 10, 2024
438f800
chore: merge main (#5449)
khatruong2009 Sep 12, 2024
b4a8ceb
chore(auth): re-generate auth cognito sdk for email mfa (#5455)
NikaHsn Sep 13, 2024
d7f3d5d
chore: fix merge changes and sdk challenge name
khatruong2009 Sep 13, 2024
c98ce74
chore: fix name of challenge to match with SDK changes and updated st…
khatruong2009 Sep 17, 2024
c1d33e3
chore: edit doc comment in auth_plugin_impl
khatruong2009 Sep 17, 2024
18a5316
chore: add emailMfaSettings to setMfaSettings
khatruong2009 Sep 17, 2024
d484c55
chore: formatting
khatruong2009 Sep 18, 2024
f604447
chore: update docs comment in constants
khatruong2009 Sep 18, 2024
b0c03b7
chore: add docs and formatting
khatruong2009 Sep 18, 2024
5153683
chore: revert package-lock.json changes
khatruong2009 Sep 18, 2024
1d37cae
chore: update mfaSetup to MfaSetupSelection
khatruong2009 Sep 18, 2024
e69d96b
chore: refactor setMfaSettings method to handle multiple mfa preferre…
khatruong2009 Sep 18, 2024
764f16d
chore: fix mfaType switch statement to reflect new name
khatruong2009 Sep 19, 2024
26becec
chore: refactor setMfaSettings method
khatruong2009 Sep 20, 2024
86a3228
chore: mark sdk_exception file as generated
khatruong2009 Sep 20, 2024
13e60c4
chore: update core docs
khatruong2009 Sep 20, 2024
0d725dc
chore: update integ tests
khatruong2009 Sep 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@

## Generated SDK files
packages/**/lib/src/sdk/src/** linguist-generated
packages/auth/amplify_auth_cognito_dart/lib/src/sdk/sdk_exception.dart linguist-generated
Copy link
Member

Choose a reason for hiding this comment

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

Q: why do we need to add this?

Copy link
Member Author

Choose a reason for hiding this comment

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

The file is generated but doesn't have the .g.dart at the end


## Generated Swift Plugins
packages/amplify_datastore/ios/internal/** linguist-generated
Expand Down
36 changes: 32 additions & 4 deletions packages/amplify_core/doc/lib/auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -104,22 +104,32 @@ Future<void> resendSignUpCode(String username) async {
}
// #enddocregion resend-signup-code

// #docregion handle-signin, handle-confirm-signin-sms, handle-confirm-signin-new-password, handle-confirm-signin-custom-challenge, handle-confirm-signin-reset-password, handle-confirm-signin-confirm-signup, handle-confirm-signin-done, handle-confirm-signin-mfa-selection, handle-confirm-signin-totp-setup, handle-confirm-signin-totp-code
// #docregion handle-signin, handle-confirm-signin-sms, handle-confirm-signin-new-password, handle-confirm-signin-custom-challenge, handle-confirm-signin-reset-password, handle-confirm-signin-confirm-signup, handle-confirm-signin-done, handle-confirm-signin-mfa-selection, handle-confirm-signin-totp-setup, handle-confirm-signin-totp-code, handle-confirm-signin-email-code, handle-confirm-signin-mfa-setup-selection, handle-confirm-signin-email-setup
Future<void> _handleSignInResult(SignInResult result) async {
switch (result.nextStep.signInStep) {
// #enddocregion handle-signin, handle-confirm-signin-sms, handle-confirm-signin-new-password, handle-confirm-signin-custom-challenge, handle-confirm-signin-reset-password, handle-confirm-signin-confirm-signup, handle-confirm-signin-done, handle-confirm-signin-mfa-selection, handle-confirm-signin-totp-setup, handle-confirm-signin-totp-code
// #enddocregion handle-signin, handle-confirm-signin-sms, handle-confirm-signin-new-password, handle-confirm-signin-custom-challenge, handle-confirm-signin-reset-password, handle-confirm-signin-confirm-signup, handle-confirm-signin-done, handle-confirm-signin-mfa-selection, handle-confirm-signin-email-code, handle-confirm-signin-totp-setup, handle-confirm-signin-totp-code, handle-confirm-signin-mfa-setup-selection, handle-confirm-signin-email-setup
// #docregion handle-confirm-signin-mfa-selection
case AuthSignInStep.continueSignInWithMfaSelection:
final allowedMfaTypes = result.nextStep.allowedMfaTypes!;
final selection = await _promptUserPreference(allowedMfaTypes);
return _handleMfaSelection(selection);
// #enddocregion handle-confirm-signin-mfa-selection
// #docregion handle-confirm-signin-mfa-setup-selection
case AuthSignInStep.continueSignInWithMfaSetupSelection:
final allowedMfaTypes = result.nextStep.allowedMfaTypes!;
final selection = await _promptUserPreference(allowedMfaTypes);
return _handleMfaSetupSelection(selection);
// #enddocregion handle-confirm-signin-mfa-setup-selection
// #docregion handle-confirm-signin-totp-setup
case AuthSignInStep.continueSignInWithTotpSetup:
final totpSetupDetails = result.nextStep.totpSetupDetails!;
final setupUri = totpSetupDetails.getSetupUri(appName: 'MyApp');
safePrint('Open URI to complete setup: $setupUri');
// #enddocregion handle-confirm-signin-totp-setup
// #docregion handle-confirm-signin-email-setup
case AuthSignInStep.continueSignInWithEmailMfaSetup:
safePrint('A confirmation code has been sent to your email');
// #enddocregion handle-confirm-signin-email-setup
// #docregion handle-confirm-signin-totp-code
case AuthSignInStep.confirmSignInWithTotpMfaCode:
safePrint('Enter a one-time code from your registered Authenticator app');
Expand All @@ -129,6 +139,11 @@ Future<void> _handleSignInResult(SignInResult result) async {
final codeDeliveryDetails = result.nextStep.codeDeliveryDetails!;
_handleCodeDelivery(codeDeliveryDetails);
// #enddocregion handle-confirm-signin-sms
// #docregion handle-confirm-signin-email
case AuthSignInStep.confirmSignInWithEmailMfaCode:
final codeDeliveryDetails = result.nextStep.codeDeliveryDetails!;
_handleCodeDelivery(codeDeliveryDetails);
// #enddocregion handle-confirm-signin-email
// #docregion handle-confirm-signin-new-password
case AuthSignInStep.confirmSignInWithNewPassword:
safePrint('Enter a new password to continue signing in');
Expand Down Expand Up @@ -158,10 +173,10 @@ Future<void> _handleSignInResult(SignInResult result) async {
case AuthSignInStep.done:
safePrint('Sign in is complete');
// #enddocregion handle-confirm-signin-done
// #docregion handle-signin, handle-confirm-signin-sms, handle-confirm-signin-new-password, handle-confirm-signin-custom-challenge, handle-confirm-signin-reset-password, handle-confirm-signin-confirm-signup, handle-confirm-signin-done, handle-confirm-signin-mfa-selection, handle-confirm-signin-totp-setup, handle-confirm-signin-totp-code
// #docregion handle-signin, handle-confirm-signin-sms, handle-confirm-signin-new-password, handle-confirm-signin-custom-challenge, handle-confirm-signin-reset-password, handle-confirm-signin-confirm-signup, handle-confirm-signin-done, handle-confirm-signin-mfa-selection, handle-confirm-signin-totp-setup, handle-confirm-signin-totp-code, handle-confirm-signin-email-code, handle-confirm-signin-mfa-setup-selection, handle-confirm-signin-email-setup
}
}
// #enddocregion handle-signin, handle-confirm-signin-sms, handle-confirm-signin-new-password, handle-confirm-signin-custom-challenge, handle-confirm-signin-reset-password, handle-confirm-signin-confirm-signup, handle-confirm-signin-done, handle-confirm-signin-mfa-selection, handle-confirm-signin-totp-setup, handle-confirm-signin-totp-code
// #enddocregion handle-signin, handle-confirm-signin-sms, handle-confirm-signin-new-password, handle-confirm-signin-custom-challenge, handle-confirm-signin-reset-password, handle-confirm-signin-confirm-signup, handle-confirm-signin-done, handle-confirm-signin-mfa-selection, handle-confirm-signin-totp-setup, handle-confirm-signin-totp-code, handle-confirm-signin-email-code, handle-confirm-signin-mfa-setup-selection, handle-confirm-signin-email-setup

// #docregion signin
Future<void> signInUser(String username, String password) async {
Expand Down Expand Up @@ -236,6 +251,19 @@ Future<void> _handleMfaSelection(MfaType selection) async {
}
// #enddocregion handle-mfa-selection

// #docregion handle-mfa-setup-selection
Future<void> _handleMfaSetupSelection(MfaType selection) async {
try {
final result = await Amplify.Auth.confirmSignIn(
confirmationValue: selection.confirmationValue,
);
return _handleSignInResult(result);
} on AuthException catch (e) {
safePrint('Error resending code: ${e.message}');
}
}
// #enddocregion handle-mfa-setup-selection

// #docregion signout
Future<void> signOutCurrentUser() async {
final result = await Amplify.Auth.signOut();
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ enum MfaMethod {
sms,

@JsonValue('TOTP')
totp;
totp,

@JsonValue('EMAIL')
email;

/// The value to pass to `Amplify.Auth.confirmSignIn` when
/// selecting an MFA type.
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ enum MfaType {
sms,

@JsonValue('TOTP')
totp;
totp,

@JsonValue('EMAIL')
email;

/// The value to pass to `Amplify.Auth.confirmSignIn` when
/// selecting an MFA type.
Expand All @@ -21,6 +24,7 @@ extension ToMfaMethod on MfaType {
return switch (this) {
MfaType.sms => MfaMethod.sms,
MfaType.totp => MfaMethod.totp,
MfaType.email => MfaMethod.email,
};
}
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,27 @@ enum AuthSignInStep {
/// an MFA method.
continueSignInWithMfaSelection,

/// The sign-in is not complete and the user must select an MFA method to setup.
continueSignInWithMfaSetupSelection,

/// The sign-in is not complete and a TOTP authenticator app must be
/// registered before continuing.
continueSignInWithTotpSetup,

/// The sign-in is not complete and an Email MFA must be set up before
/// continuing.
continueSignInWithEmailMfaSetup,

/// The sign-in is not complete and must be confirmed with an SMS code.
confirmSignInWithSmsMfaCode,

/// The sign-in is not complete and must be confirmed with a TOTP code
/// from a registered authenticator app.
confirmSignInWithTotpMfaCode,

/// The sign-in is not complete and must be confirmed with an email code.
confirmSignInWithEmailMfaCode,

/// The sign-in is not complete and must be confirmed with the user's new
/// password.
confirmSignInWithNewPassword,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void main() {
signInRes.nextStep.signInStep,
because: 'MFA is required, and TOTP is chosen when '
'no phone number is registered',
).equals(AuthSignInStep.continueSignInWithTotpSetup);
).equals(AuthSignInStep.continueSignInWithMfaSetupSelection);
Copy link
Member

Choose a reason for hiding this comment

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

Q: Is this expected? If so, why is it different than before?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, it's expected because before there was only the set up totp option that users could set up when setting up MFA but now there's email added to that. So now there's an extra step injected so that users can choose which mfa method they want to set up when previously they didn't have a choice.


final sharedSecret = signInRes.nextStep.totpSetupDetails!.sharedSecret;
final setupRes = await Amplify.Auth.confirmSignIn(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ void main() {
signInRes.nextStep.signInStep,
because:
"TOTP MFA is automatically enabled when it's the only option",
).equals(AuthSignInStep.continueSignInWithTotpSetup);
).equals(AuthSignInStep.continueSignInWithMfaSetupSelection);

final sharedSecret = signInRes.nextStep.totpSetupDetails!.sharedSecret;
final setupRes = await Amplify.Auth.confirmSignIn(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -885,20 +885,22 @@ class AmplifyAuthCognitoDart extends AuthPluginInterface
/// {@template amplify_core.amplify_auth_category.update_mfa_preference}
/// Updates the MFA preference for the current user.
///
/// If [sms] or [totp] is `null`, the preference for that MFA type is left
/// unchanged. Setting either [sms] or [totp] to [MfaPreference.preferred]
/// If [sms], [totp], or [email] is `null`, the preference for that MFA type is left
/// unchanged. Setting either [sms], [totp], or [email] to [MfaPreference.preferred]
/// will mark the other as not preferred.
/// {@endtemplate}
Future<void> updateMfaPreference({
MfaPreference? sms,
MfaPreference? totp,
MfaPreference? email,
}) async {
final tokens = await _stateMachine.getUserPoolTokens();
final accessToken = tokens.accessToken.raw;
return _cognitoIdp.setMfaSettings(
accessToken: accessToken,
sms: sms,
totp: totp,
email: email,
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ abstract class CognitoConstants {
/// The `SMS_MFA_CODE` parameter.
static const challengeParamSmsMfaCode = 'SMS_MFA_CODE';

/// The `EMAIL_OTP_CODE` parameter.
static const challengeParamEmailMfaCode = 'EMAIL_OTP_CODE';
Copy link
Member

Choose a reason for hiding this comment

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

Q: should this be 'EMAIL_MFA_CODE'?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is to match the Cognito team renaming it to EMAIL_OTP rather than MFA.


/// The `SOFTWARE_TOKEN_MFA_CODE` parameter.
static const challengeParamSoftwareTokenMfaCode = 'SOFTWARE_TOKEN_MFA_CODE';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Generated with smithy-dart 0.3.1. DO NOT MODIFY.
// Generated with smithy-dart 0.3.2. DO NOT MODIFY.
// ignore_for_file: avoid_unused_constructor_parameters,deprecated_member_use_from_same_package,non_constant_identifier_names,require_trailing_commas

/// # Amazon Cognito Identity
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Generated with smithy-dart 0.3.1. DO NOT MODIFY.
// Generated with smithy-dart 0.3.2. DO NOT MODIFY.
// ignore_for_file: avoid_unused_constructor_parameters,deprecated_member_use_from_same_package,non_constant_identifier_names,require_trailing_commas

/// # Amazon Cognito Identity Provider
Expand Down Expand Up @@ -68,6 +68,7 @@ export 'package:amplify_auth_cognito_dart/src/sdk/src/cognito_identity_provider/
export 'package:amplify_auth_cognito_dart/src/sdk/src/cognito_identity_provider/model/device_remembered_status_type.dart';
export 'package:amplify_auth_cognito_dart/src/sdk/src/cognito_identity_provider/model/device_secret_verifier_config_type.dart';
export 'package:amplify_auth_cognito_dart/src/sdk/src/cognito_identity_provider/model/device_type.dart';
export 'package:amplify_auth_cognito_dart/src/sdk/src/cognito_identity_provider/model/email_mfa_settings_type.dart';
export 'package:amplify_auth_cognito_dart/src/sdk/src/cognito_identity_provider/model/enable_software_token_mfa_exception.dart';
export 'package:amplify_auth_cognito_dart/src/sdk/src/cognito_identity_provider/model/expired_code_exception.dart';
export 'package:amplify_auth_cognito_dart/src/sdk/src/cognito_identity_provider/model/forbidden_exception.dart';
Expand Down Expand Up @@ -99,6 +100,7 @@ export 'package:amplify_auth_cognito_dart/src/sdk/src/cognito_identity_provider/
export 'package:amplify_auth_cognito_dart/src/sdk/src/cognito_identity_provider/model/mfa_option_type.dart';
export 'package:amplify_auth_cognito_dart/src/sdk/src/cognito_identity_provider/model/new_device_metadata_type.dart';
export 'package:amplify_auth_cognito_dart/src/sdk/src/cognito_identity_provider/model/not_authorized_exception.dart';
export 'package:amplify_auth_cognito_dart/src/sdk/src/cognito_identity_provider/model/password_history_policy_violation_exception.dart';
export 'package:amplify_auth_cognito_dart/src/sdk/src/cognito_identity_provider/model/password_reset_required_exception.dart';
export 'package:amplify_auth_cognito_dart/src/sdk/src/cognito_identity_provider/model/resend_confirmation_code_request.dart';
export 'package:amplify_auth_cognito_dart/src/sdk/src/cognito_identity_provider/model/resend_confirmation_code_response.dart';
Expand Down
Loading
Loading