Skip to content

feat: add email MFA steps to Authenticator #5389

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

Merged
merged 93 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from 92 commits
Commits
Show all changes
93 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
69abe75
chore: update core docs example
khatruong2009 Oct 4, 2024
970bf15
chore: add authenticator state/step enums
khatruong2009 Oct 4, 2024
5586c16
chore: change state machine and auth bloc to automatically move state…
khatruong2009 Oct 4, 2024
4725074
chore: add email mfa to test_runner
khatruong2009 Oct 4, 2024
f0b69a3
chore: dart format
khatruong2009 Oct 4, 2024
7b901af
chore: fix auth.dart docs
khatruong2009 Oct 7, 2024
66097f2
chore: moved ChallengeNameType.mfaSetup switch statement logic to a h…
khatruong2009 Oct 7, 2024
0fdcc15
chore: flatten an if statement in the helper method by adding mfaType…
khatruong2009 Oct 7, 2024
e630a30
chore: dart format
khatruong2009 Oct 7, 2024
334e8b3
chore: remove extra if checks and add null check
khatruong2009 Oct 7, 2024
87bb72b
chore: dart format
khatruong2009 Oct 7, 2024
c4ee27d
chore: add back in mfaTypesForSetup instead of allowedMfaTypes
khatruong2009 Oct 7, 2024
c89773b
chore: add ChallengeName
khatruong2009 Aug 2, 2024
255aaa6
Revert "chore: add ChallengeName"
khatruong2009 Aug 5, 2024
d7a5700
chore: merge main (#5449)
khatruong2009 Sep 12, 2024
479a034
chore: revert package-lock.json changes
khatruong2009 Sep 18, 2024
1eefc27
chore: add new AuthenticatorStep to switch statements in screen
khatruong2009 Aug 28, 2024
fd0db6f
chore: add input resolvers and localizations
khatruong2009 Aug 30, 2024
2f466d7
chore: add keys and enums
khatruong2009 Aug 30, 2024
69fa04e
chore: add select email input resolver
khatruong2009 Aug 30, 2024
059213d
chore: add EmailSetupField type for authenticator
khatruong2009 Sep 3, 2024
111f35e
chore: add switch cases for future implementations of the forms
khatruong2009 Sep 3, 2024
8f2ccdf
chore: add authenticator step cases for sign in with email mfa
khatruong2009 Sep 4, 2024
db1409a
chore: remove code from email setup field because only email is needed
khatruong2009 Sep 4, 2024
bafad94
chore: add mfa email to authenticator state
khatruong2009 Sep 4, 2024
c4b809b
chore: add email mfa setup form and form field
khatruong2009 Sep 4, 2024
a07f13b
chore: adding steps to authenticator state machine
khatruong2009 Sep 5, 2024
0b09af1
chore: remove this verification code form field key since we already …
khatruong2009 Sep 6, 2024
362f97c
chore: add authenticator screen keys for new screens
khatruong2009 Sep 6, 2024
6dfa933
chore: remove dart auto formatted code
khatruong2009 Sep 6, 2024
49d1d28
chore: add new email mfa setup form to inherited forms switch statement
khatruong2009 Sep 6, 2024
845892e
chore: add cases to oldWidget
khatruong2009 Sep 6, 2024
8000bec
chore: add todo to add case for continueSignInWithMfaSetupSelection
khatruong2009 Sep 6, 2024
d6cd995
chore: remove duplicate localization and fix docs comments
khatruong2009 Sep 19, 2024
9af619d
chore: add continueSignInWithMfaSetupSelectionForm
khatruong2009 Sep 19, 2024
a8b41e9
chore: dart format and fix typos
khatruong2009 Sep 19, 2024
3b50a1b
chore: fix mfaSetup fields and input_resolver duplicate
khatruong2009 Sep 19, 2024
dab8ff4
chore: remove duplicate analytics backend section
khatruong2009 Sep 25, 2024
8b7771d
chore: use confirmSignInWithEmailMfaCode instead of confirmSignInMfa
khatruong2009 Sep 26, 2024
93a8b75
chore: dart format
khatruong2009 Oct 2, 2024
64f25ad
chore: add trailing comma
khatruong2009 Oct 2, 2024
7fd3b39
chore: dart format
khatruong2009 Oct 2, 2024
dd76942
chore: doc fixes
khatruong2009 Oct 11, 2024
d602bef
chore: fixed else statement circular loop
khatruong2009 Oct 11, 2024
e98a31c
chore: dart format
khatruong2009 Oct 11, 2024
d7ebd26
chore: dart format authenticator
khatruong2009 Oct 11, 2024
aad9883
chore: add trailing comma
khatruong2009 Oct 11, 2024
9d9abe8
chore: dart format
khatruong2009 Oct 11, 2024
0641f33
temp state machine changes
khatruong2009 Oct 9, 2024
d7dc6bc
chore: fix inherited_forms steps
khatruong2009 Oct 11, 2024
2cd215b
chore: adjust continue sign in with email mfa setup form
khatruong2009 Oct 11, 2024
495ff1e
chore: refactor large nested if statement blocks in state machine
khatruong2009 Oct 11, 2024
e1bf813
chore: auth_bloc refactor to separate logic into a helper function an…
khatruong2009 Oct 11, 2024
cd610ea
chore: fix the email setup form field
khatruong2009 Oct 14, 2024
1d44a2e
chore: fix totp selection flow
khatruong2009 Oct 14, 2024
02fb1a6
chore: remove safePrint
khatruong2009 Oct 14, 2024
85368f1
chore: dart format
khatruong2009 Oct 14, 2024
e7e0888
chore: refactor setMfaSettings to make it easier to read with helper …
khatruong2009 Oct 15, 2024
4135f06
chore: refactor auth_bloc with helper function used in two switch sta…
khatruong2009 Oct 15, 2024
eb93be4
chore: refactor auth bloc helper method to remove nested if/else stat…
khatruong2009 Oct 15, 2024
daacad7
chore: refactor sign in state machine and add in constants for email …
khatruong2009 Oct 15, 2024
a3c57e9
chore: fix missing !
khatruong2009 Oct 15, 2024
7129360
chore: run dart format
khatruong2009 Oct 15, 2024
4c470eb
Merge branch 'feat/email-otp-mfa-enum' into feat/email-otp-authenticator
khatruong2009 Oct 15, 2024
7c79ec3
Merge branch 'feat/email-otp-mfa' into feat/email-otp-authenticator
khatruong2009 Oct 17, 2024
4eb2093
chore: add emit to processSignInResult
khatruong2009 Oct 17, 2024
37c769d
chore: add mfa setup selection in authenticator step in form field
khatruong2009 Oct 22, 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
5 changes: 0 additions & 5 deletions infra-gen2/tool/deploy_gen2.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@ import 'package:path/path.dart' as p;
/// 3. Add the backend to a category or create a new category
/// 4. Run `dart tool/deploy_gen2.dart` to deploy the backend
const List<AmplifyBackendGroup> infraConfig = [
AmplifyBackendGroup(
category: Category.analytics,
defaultOutput: '',
backends: [],
),
AmplifyBackendGroup(
category: Category.api,
defaultOutput: 'packages/api/amplify_api/example/lib',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -481,45 +481,45 @@ class AmplifyAuthCognitoDart extends AuthPluginInterface
}

CognitoSignInResult _processSignInResult(SignInState result) {
return switch (result) {
SignInNotStarted _ ||
SignInInitiating _ =>
switch (result) {
case SignInNotStarted():
case SignInInitiating():
// This should never happen.
throw UnknownException(
'Sign in could not be completed',
underlyingException: result,
),
SignInCancelling _ => throw const UserCancelledException(
);

case SignInCancelling():
throw const UserCancelledException(
'The user canceled the sign-in flow',
),
SignInChallenge(
:final challengeName,
:final challengeParameters,
:final codeDeliveryDetails,
:final requiredAttributes,
:final allowedMfaTypes,
:final totpSetupResult,
) =>
CognitoSignInResult(
);

case final SignInChallenge challenge:
return CognitoSignInResult(
isSignedIn: false,
nextStep: AuthNextSignInStep(
signInStep: challengeName.signInStep,
codeDeliveryDetails: codeDeliveryDetails,
additionalInfo: challengeParameters,
missingAttributes: requiredAttributes,
allowedMfaTypes: allowedMfaTypes,
totpSetupDetails: totpSetupResult,
signInStep: challenge.challengeName.signInStep,
codeDeliveryDetails: challenge.codeDeliveryDetails,
additionalInfo: challenge.challengeParameters,
missingAttributes: challenge.requiredAttributes,
allowedMfaTypes: challenge.allowedMfaTypes,
totpSetupDetails: challenge.totpSetupResult,
),
),
SignInSuccess _ => const CognitoSignInResult(
);

case SignInSuccess():
return const CognitoSignInResult(
isSignedIn: true,
nextStep: AuthNextSignInStep(
signInStep: AuthSignInStep.done,
),
),
SignInFailure(:final exception, :final stackTrace) =>
Error.throwWithStackTrace(exception, stackTrace),
};
);

case final SignInFailure failure:
Error.throwWithStackTrace(failure.exception, failure.stackTrace);
// To satisfy Dart's requirements, even if unreachable
}
}

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ export 'src/widgets/form.dart'
ConfirmSignInMFAForm,
ConfirmSignInNewPasswordForm,
ContinueSignInWithMfaSelectionForm,
ContinueSignInWithMfaSetupSelectionForm,
ContinueSignInWithTotpSetupForm,
ContinueSignInWithEmailMfaSetupForm,
ConfirmSignUpForm,
ResetPasswordForm,
ConfirmResetPasswordForm,
Expand Down Expand Up @@ -710,9 +712,14 @@ class _AuthenticatorState extends State<Authenticator> {
confirmSignInMFAForm: ConfirmSignInMFAForm(),
continueSignInWithMfaSelectionForm:
ContinueSignInWithMfaSelectionForm(),
continueSignInWithMfaSetupSelectionForm:
ContinueSignInWithMfaSetupSelectionForm(),
continueSignInWithTotpSetupForm:
ContinueSignInWithTotpSetupForm(),
continueSignInWithEmailMfaSetupForm:
ContinueSignInWithEmailMfaSetupForm(),
confirmSignInWithTotpMfaCodeForm: ConfirmSignInMFAForm(),
confirmSignInWithEmailMfaCodeForm: ConfirmSignInMFAForm(),
verifyUserForm: VerifyUserForm(),
confirmVerifyUserForm: ConfirmVerifyUserForm(),
child: widget.child,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ class StateMachineBloc
),
);
case AuthSignInStep.continueSignInWithMfaSetupSelection:
await _handleMfaSetupSelection(result);
_emit(await _handleMfaSetupSelection(result));
case AuthSignInStep.continueSignInWithEmailMfaSetup:
_emit(UnauthenticatedState.continueSignInWithEmailMfaSetup);
case AuthSignInStep.confirmSignInWithTotpMfaCode:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

enum EmailSetupField {
email,
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
export 'authenticator_step.dart';
export 'confirm_signin_types.dart';
export 'confirm_signup_types.dart';
export 'email_setup_types.dart';
export 'gender.dart';
export 'reset_password_field.dart';
export 'signin_types.dart';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ const keyCustomChallengeConfirmSignInFormField =
Key('customChallengeConfirmSignInFormField');
const keyMfaMethodRadioConfirmSignInFormField =
Key('mfaMethodRadioConfirmSignInFormField');
const keyMfaSetupMethodRadioConfirmSignInFormField =
Key('mfaSetupMethodRadioConfirmSignInFormField');
const keyUsernameConfirmSignInFormField = Key('usernameConfirmSignInFormField');
const keyPasswordConfirmSignInFormField = Key('passwordConfirmSignInFormField');
const keyNewPasswordConfirmSignInFormField =
Expand Down Expand Up @@ -107,6 +109,10 @@ const keyGoToSignInButton = Key('goToSignInButton');
const keyConfirmSignInButton = Key('confirmSignInButton');
const keyConfirmSignInMfaSelectionButton =
Key('confirmSignInMfaSelectionButton');
const keyConfirmSignInMfaSetupSelectionButton =
Key('confirmSignInMfaSetupSelectionButton');
const keyConfirmSignInWithEmailMfaSetupButton =
Key('confirmSignInWithEmailMfaSetupButton');
const keyConfirmSignInCustomButton = Key('confirmSignInCustomButton');
const keyLostCodeButton = Key('lostCodeButton');
const keySendCodeButton = Key('sendCodeButton');
Expand Down Expand Up @@ -140,3 +146,6 @@ const keyAuthenticatorBanner = Key('authenticatorBanner');
const keyQrCodeTotpSetupFormField = Key('qrCodeTotpSetupFormField');
const keyCopyKeyTotpSetupFormField = Key('copyKeyTotpSetupFormField');
const keyTotpSetupFormField = Key('totpSetupFormField');

// Email setup form keys
const keyEmailSetupFormField = Key('emailSetupFormField');
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,24 @@ abstract class AuthenticatorTitleLocalizations {
/// **'Enter your one-time passcode'**
String get confirmSignInWithTotpMfaCode;

/// Title of the Confirm Sign In with Email MFA Code step and form
///
/// In en, this message translates to:
/// **'Enter your one-time passcode'**
String get confirmSignInWithEmailMfaCode;

/// Title of the Continue Sign In with Email MFA Setup step and form
///
/// In en, this message translates to:
/// **'Add Email for Two-Factor Authentication'**
String get continueSignInWithEmailMfaSetup;

/// Title of the Continue Sign In with MFA Setup Selection step and form
///
/// In en, this message translates to:
/// **'Choose your preferred two-factor authentication method to set up'**
String get continueSignInWithMfaSetupSelection;

/// Title of the Reset Password step and form
///
/// In en, this message translates to:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ class AuthenticatorTitleLocalizationsEn
@override
String get confirmSignInWithTotpMfaCode => 'Enter your one-time passcode';

@override
String get confirmSignInWithEmailMfaCode => 'Enter your one-time passcode';

@override
String get continueSignInWithEmailMfaSetup =>
'Add Email for Two-Factor Authentication';

@override
String get continueSignInWithMfaSetupSelection =>
'Choose your preferred two-factor authentication method to set up';

@override
String get resetPassword => 'Send Code';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ class InputResolverKey {

static const selectEmail = InputResolverKey._(
InputResolverKeyType.title,
field: InputField.email,
field: InputField.selectEmail,
);

static const totpCodePrompt = InputResolverKey._(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,5 +216,9 @@
"totpCodePrompt": "Please enter the code from your registered Authenticator app",
"@totpCodePrompt": {
"description": "The instructional text for submitting a TOTP pass code"
}
},
"selectEmail": "Email",
"@selectEmail": {
"description": "Label for the radio button to select email as the user's chosen MFA method."
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,24 @@ class TitleResolver extends Resolver<AuthenticatorStep> {
.confirmSignInWithTotpMfaCode;
}

/// The title for the confirm sign in (email MFA code) Widget.
String confirmSignInWithEmailMfaCode(BuildContext context) {
return AuthenticatorLocalizations.titlesOf(context)
.confirmSignInWithEmailMfaCode;
}

/// The title for the continue sign in (email MFA setup) Widget.
String continueSignInWithEmailMfaSetup(BuildContext context) {
return AuthenticatorLocalizations.titlesOf(context)
.continueSignInWithEmailMfaSetup;
}

/// The title for the continue sign in (mfa setup selection) Widget.
String continueSignInWithMfaSetupSelection(BuildContext context) {
return AuthenticatorLocalizations.titlesOf(context)
.continueSignInWithMfaSetupSelection;
}

/// The title for the reset password Widget.
String resetPassword(BuildContext context) {
return AuthenticatorLocalizations.titlesOf(context).resetPassword;
Expand Down Expand Up @@ -81,6 +99,12 @@ class TitleResolver extends Resolver<AuthenticatorStep> {
return continueSignInWithTotpSetup(context);
case AuthenticatorStep.confirmSignInWithTotpMfaCode:
return confirmSignInWithTotpMfaCode(context);
case AuthenticatorStep.confirmSignInWithEmailMfaCode:
return confirmSignInWithEmailMfaCode(context);
case AuthenticatorStep.continueSignInWithEmailMfaSetup:
return continueSignInWithEmailMfaSetup(context);
case AuthenticatorStep.continueSignInWithMfaSetupSelection:
return continueSignInWithMfaSetupSelection(context);
case AuthenticatorStep.resetPassword:
return resetPassword(context);
case AuthenticatorStep.confirmResetPassword:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ class AuthenticatorScreen extends StatelessAuthenticatorComponent {
const AuthenticatorScreen.confirmSignInWithTotpMfaCode({Key? key})
: this(key: key, step: AuthenticatorStep.confirmSignInWithTotpMfaCode);

const AuthenticatorScreen.confirmSignInWithEmailMfaCode({Key? key})
: this(key: key, step: AuthenticatorStep.confirmSignInWithEmailMfaCode);

const AuthenticatorScreen.continueSignInWithEmailMfaSetup({Key? key})
: this(key: key, step: AuthenticatorStep.continueSignInWithEmailMfaSetup);

const AuthenticatorScreen.continueSignInWithMfaSetupSelection({Key? key})
: this(
key: key,
step: AuthenticatorStep.continueSignInWithMfaSetupSelection,
);

const AuthenticatorScreen.resetPassword({Key? key})
: this(key: key, step: AuthenticatorStep.resetPassword);

Expand Down Expand Up @@ -91,6 +103,9 @@ class AuthenticatorScreen extends StatelessAuthenticatorComponent {
case AuthenticatorStep.confirmResetPassword:
case AuthenticatorStep.verifyUser:
case AuthenticatorStep.confirmVerifyUser:
case AuthenticatorStep.confirmSignInWithEmailMfaCode:
case AuthenticatorStep.continueSignInWithEmailMfaSetup:
case AuthenticatorStep.continueSignInWithMfaSetupSelection:
child = _FormWrapperView(step: step);
case AuthenticatorStep.loading:
throw StateError('Invalid step: $this');
Expand Down Expand Up @@ -299,6 +314,9 @@ extension on AuthenticatorStep {
case AuthenticatorStep.verifyUser:
case AuthenticatorStep.confirmVerifyUser:
case AuthenticatorStep.loading:
case AuthenticatorStep.confirmSignInWithEmailMfaCode:
case AuthenticatorStep.continueSignInWithEmailMfaSetup:
case AuthenticatorStep.continueSignInWithMfaSetupSelection:
throw StateError('Invalid step: $this');
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,18 @@ class AuthenticatorState extends ChangeNotifier {
notifyListeners();
}

/// The value for the email MFA setup form field
///
/// This value will be used during continue email MFA setup
String get mfaEmail => _mfaEmail;

set mfaEmail(String value) {
_mfaEmail = value.trim();
notifyListeners();
}

String _mfaEmail = '';

MfaType? _selectedMfaMethod;

TotpSetupDetails? get totpSetupDetails {
Expand Down Expand Up @@ -395,6 +407,23 @@ class AuthenticatorState extends ChangeNotifier {
_setIsBusy(false);
}

/// Select MFA setup preference using the values for [selectedMfaMethod]
Future<void> continueSignInWithMfaSetupSelection() async {
if (!_formKey.currentState!.validate()) {
return;
}

_setIsBusy(true);

final confirm = AuthConfirmSignInData(
confirmationValue: _selectedMfaMethod!.name,
);

_authBloc.add(AuthConfirmSignIn(confirm));
await nextBlocEvent();
_setIsBusy(false);
}

/// Complete TOTP setup using the values for [confirmationCode]
/// and any user attributes.
Future<void> confirmTotp() async {
Expand All @@ -414,6 +443,40 @@ class AuthenticatorState extends ChangeNotifier {
_setIsBusy(false);
}

/// complete Email MFA setup using the values for [confirmationCode]
Future<void> confirmEmailMfa() async {
if (!_formKey.currentState!.validate()) {
return;
}

_setIsBusy(true);

final confirm = AuthConfirmSignInData(
confirmationValue: _confirmationCode.trim(),
);

_authBloc.add(AuthConfirmSignIn(confirm));
await nextBlocEvent();
_setIsBusy(false);
}

/// Complete MFA setup using the values for [confirmationCode]
Future<void> continueEmailMfaSetup() async {
if (!_formKey.currentState!.validate()) {
return;
}

_setIsBusy(true);

final confirm = AuthConfirmSignInData(
confirmationValue: _mfaEmail.trim(),
);

_authBloc.add(AuthConfirmSignIn(confirm));
await nextBlocEvent();
_setIsBusy(false);
}

/// Complete the force password change with [newPassword]
Future<void> confirmSignInNewPassword() async {
if (!_formKey.currentState!.validate()) {
Expand Down Expand Up @@ -644,6 +707,7 @@ class AuthenticatorState extends ChangeNotifier {
authAttributes.clear();
_publicChallengeParams.clear();
_selectedMfaMethod = null;
_mfaEmail = '';
}

void _resetFormKey() {
Expand Down
Loading
Loading