Skip to content

Commit 14bb1eb

Browse files
committed
chore: add test for mfa setup selection screen in amplify auth cognito
1 parent 0bd0842 commit 14bb1eb

File tree

1 file changed

+261
-0
lines changed

1 file changed

+261
-0
lines changed
Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
5+
import 'package:amplify_auth_integration_test/amplify_auth_integration_test.dart';
6+
import 'package:amplify_flutter/amplify_flutter.dart';
7+
import 'package:amplify_integration_test/amplify_integration_test.dart';
8+
import 'package:checks/checks.dart';
9+
import 'package:flutter_test/flutter_test.dart';
10+
11+
import 'test_runner.dart';
12+
13+
void main() {
14+
testRunner.setupTests();
15+
16+
group('MFA (EMAIL + TOTP + SMS)', () {
17+
testRunner.withEnvironment(mfaRequiredUsernameLogin, (env) {
18+
asyncTest('can set up EMAIL MFA', (_) async {
19+
final username = env.generateUsername();
20+
final password = generatePassword();
21+
final email = generateEmail();
22+
23+
final otpResult = await getOtpCode(UserAttribute.email(email));
24+
25+
// Create a user with no phone number.
26+
await adminCreateUser(
27+
username,
28+
password,
29+
autoConfirm: true,
30+
autoFillAttributes: false,
31+
verifyAttributes: false,
32+
);
33+
34+
final signInRes = await Amplify.Auth.signIn(
35+
username: username,
36+
password: password,
37+
);
38+
39+
check(
40+
signInRes.nextStep.signInStep,
41+
because:
42+
'When an email is registered and the userpool has email MFA enabled, Cognito will automatically enable email MFA as the preferred MFA method.',
43+
).equals(AuthSignInStep.continueSignInWithMfaSetupSelection);
44+
45+
final selectRes = await Amplify.Auth.confirmSignIn(
46+
confirmationValue: 'EMAIL',
47+
);
48+
49+
final setupRes = await Amplify.Auth.confirmSignIn(
50+
confirmationValue: email,
51+
);
52+
53+
final confirmRes = await Amplify.Auth.confirmSignIn(
54+
confirmationValue: await otpResult.code,
55+
);
56+
57+
check(confirmRes.nextStep.signInStep).equals(AuthSignInStep.done);
58+
59+
check(await cognitoPlugin.fetchMfaPreference()).equals(
60+
const UserMfaPreference(
61+
enabled: {MfaType.email},
62+
preferred: MfaType.email,
63+
),
64+
);
65+
66+
await signOutUser(assertComplete: true);
67+
68+
final resignInRes = await Amplify.Auth.signIn(
69+
username: username,
70+
password: password,
71+
);
72+
check(resignInRes.nextStep.signInStep)
73+
.equals(AuthSignInStep.confirmSignInWithEmailMfaCode);
74+
check(resignInRes.nextStep.codeDeliveryDetails)
75+
.isNotNull()
76+
.has((d) => d.deliveryMedium, 'deliveryMedium')
77+
.equals(DeliveryMedium.email);
78+
79+
final otpResult2 = await getOtpCode(UserAttribute.email(email));
80+
final confirmRes2 = await Amplify.Auth.confirmSignIn(
81+
confirmationValue: await otpResult2.code,
82+
);
83+
check(confirmRes2.nextStep.signInStep).equals(AuthSignInStep.done);
84+
});
85+
86+
asyncTest('can setup TOTP MFA', (_) async {
87+
final username = env.generateUsername();
88+
final password = generatePassword();
89+
90+
// Create a user with an unverified phone number.
91+
await adminCreateUser(
92+
username,
93+
password,
94+
autoConfirm: true,
95+
verifyAttributes: false,
96+
autoFillAttributes: false,
97+
);
98+
99+
{
100+
final signInRes = await Amplify.Auth.signIn(
101+
username: username,
102+
password: password,
103+
);
104+
check(
105+
signInRes.nextStep.signInStep,
106+
because: 'MFA is required so users select a method to setup',
107+
).equals(AuthSignInStep.continueSignInWithMfaSetupSelection);
108+
109+
final selectRes = await Amplify.Auth.confirmSignIn(
110+
confirmationValue: 'TOTP',
111+
);
112+
113+
final sharedSecret =
114+
selectRes.nextStep.totpSetupDetails!.sharedSecret;
115+
final setupRes = await Amplify.Auth.confirmSignIn(
116+
confirmationValue: await generateTotpCode(sharedSecret),
117+
options: const ConfirmSignInOptions(
118+
pluginOptions: CognitoConfirmSignInPluginOptions(
119+
friendlyDeviceName: friendlyDeviceName,
120+
),
121+
),
122+
);
123+
124+
check(setupRes.nextStep.signInStep).equals(AuthSignInStep.done);
125+
}
126+
127+
check(
128+
await cognitoPlugin.fetchMfaPreference(),
129+
because:
130+
'MFA is required so Cognito automatically enables EMAIL MFA, this is expected behavior',
131+
).equals(
132+
const UserMfaPreference(
133+
enabled: {MfaType.totp},
134+
preferred: MfaType.totp,
135+
),
136+
);
137+
138+
await signOutUser(assertComplete: true);
139+
});
140+
141+
asyncTest(
142+
'Can set up EMAIL and TOTP MFA and then choose a preferred method',
143+
(_) async {
144+
final username = env.generateUsername();
145+
final password = generatePassword();
146+
final email = generateEmail();
147+
148+
final otpResult = await getOtpCode(UserAttribute.email(email));
149+
150+
// Create a user with no phone number.
151+
await adminCreateUser(
152+
username,
153+
password,
154+
autoConfirm: true,
155+
autoFillAttributes: false,
156+
verifyAttributes: false,
157+
);
158+
159+
final signInRes = await Amplify.Auth.signIn(
160+
username: username,
161+
password: password,
162+
);
163+
164+
check(
165+
signInRes.nextStep.signInStep,
166+
because:
167+
'When both EMAIL and TOTP are enabled but email attribute isnt verified, choose an mfa method to set up.',
168+
).equals(AuthSignInStep.continueSignInWithMfaSetupSelection);
169+
170+
final selectRes = await Amplify.Auth.confirmSignIn(
171+
confirmationValue: 'EMAIL',
172+
);
173+
174+
final setupRes = await Amplify.Auth.confirmSignIn(
175+
confirmationValue: email,
176+
);
177+
178+
final confirmRes = await Amplify.Auth.confirmSignIn(
179+
confirmationValue: await otpResult.code,
180+
);
181+
182+
check(confirmRes.nextStep.signInStep).equals(AuthSignInStep.done);
183+
184+
check(await cognitoPlugin.fetchMfaPreference()).equals(
185+
const UserMfaPreference(
186+
enabled: {MfaType.email},
187+
preferred: MfaType.email,
188+
),
189+
);
190+
191+
await signOutUser(assertComplete: true);
192+
193+
final resignInRes = await Amplify.Auth.signIn(
194+
username: username,
195+
password: password,
196+
);
197+
198+
final otpResult2 = await getOtpCode(UserAttribute.email(email));
199+
200+
check(resignInRes.nextStep.signInStep)
201+
.equals(AuthSignInStep.confirmSignInWithEmailMfaCode);
202+
check(resignInRes.nextStep.codeDeliveryDetails)
203+
.isNotNull()
204+
.has((d) => d.deliveryMedium, 'deliveryMedium')
205+
.equals(DeliveryMedium.email);
206+
207+
safePrint('RESIGN IN RES: $resignInRes');
208+
209+
final confirmRes2 = await Amplify.Auth.confirmSignIn(
210+
confirmationValue: await otpResult2.code,
211+
);
212+
check(confirmRes2.nextStep.signInStep).equals(AuthSignInStep.done);
213+
214+
await setUpTotp();
215+
216+
check(await cognitoPlugin.fetchMfaPreference()).equals(
217+
const UserMfaPreference(
218+
enabled: {MfaType.email, MfaType.totp},
219+
preferred: null,
220+
),
221+
);
222+
223+
// await cognitoPlugin.updateMfaPreference(
224+
// totp: MfaPreference.preferred,
225+
// );
226+
227+
// check(setupRes.nextStep.signInStep).equals(AuthSignInStep.done);
228+
229+
// sign out and sign back in and confirm TOTP
230+
await signOutUser(assertComplete: true);
231+
232+
final resignInRes2 = await Amplify.Auth.signIn(
233+
username: username,
234+
password: password,
235+
);
236+
237+
safePrint('RESIGN IN RES 2: $resignInRes2');
238+
239+
check(resignInRes2.nextStep.signInStep)
240+
.equals(AuthSignInStep.continueSignInWithMfaSelection);
241+
242+
// select totp as the preferred method
243+
final selectRes2 = await Amplify.Auth.confirmSignIn(
244+
confirmationValue: 'TOTP',
245+
);
246+
247+
safePrint('SELECT RES 2: $selectRes2');
248+
249+
// final sharedSecret =
250+
// selectRes2.nextStep.totpSetupDetails!.sharedSecret;
251+
252+
final confirmRes3 = await Amplify.Auth.confirmSignIn(
253+
confirmationValue: await generateTotpCode(),
254+
);
255+
256+
check(confirmRes3.nextStep.signInStep).equals(AuthSignInStep.done);
257+
},
258+
);
259+
});
260+
});
261+
}

0 commit comments

Comments
 (0)