Skip to content

Commit

Permalink
test(auth): TOTP MFA tests
Browse files Browse the repository at this point in the history
Adds E2E tests for TOTP MFA and splits existing MFA tests by backend configuration: SMS, TOTP, and SMS/TOTP.
  • Loading branch information
Dillon Nys committed Aug 17, 2023
1 parent 8a11238 commit 72f11e9
Show file tree
Hide file tree
Showing 29 changed files with 1,623 additions and 205 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,10 @@ void main() {
password,
autoConfirm: true,
verifyAttributes: true,
attributes: [
AuthUserAttribute(
userAttributeKey: CognitoUserAttributeKey.email,
value: email,
),
AuthUserAttribute(
userAttributeKey: CognitoUserAttributeKey.phoneNumber,
value: phoneNumber,
),
],
attributes: {
CognitoUserAttributeKey.email: email,
CognitoUserAttributeKey.phoneNumber: phoneNumber,
},
);

final signInResult = await Amplify.Auth.signIn(
Expand All @@ -114,16 +108,10 @@ void main() {
autoConfirm: true,
verifyAttributes: true,
enableMfa: true,
attributes: [
AuthUserAttribute(
userAttributeKey: CognitoUserAttributeKey.email,
value: email,
),
AuthUserAttribute(
userAttributeKey: CognitoUserAttributeKey.phoneNumber,
value: phoneNumber,
),
],
attributes: {
CognitoUserAttributeKey.email: email,
CognitoUserAttributeKey.phoneNumber: phoneNumber,
},
);

final signInCode = await getOtpCode(
Expand Down Expand Up @@ -156,16 +144,10 @@ void main() {
password,
autoConfirm: true,
verifyAttributes: true,
attributes: [
AuthUserAttribute(
userAttributeKey: CognitoUserAttributeKey.email,
value: email,
),
AuthUserAttribute(
userAttributeKey: CognitoUserAttributeKey.phoneNumber,
value: phoneNumber,
),
],
attributes: {
CognitoUserAttributeKey.email: email,
CognitoUserAttributeKey.phoneNumber: phoneNumber,
},
);

final signInResult = await Amplify.Auth.signIn(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,9 @@ void main() {
password,
autoConfirm: false,
autoFillAttributes: false,
attributes: [
AuthUserAttribute(
userAttributeKey: AuthUserAttributeKey.phoneNumber,
value: phoneNumber,
),
],
attributes: {
AuthUserAttributeKey.phoneNumber: phoneNumber,
},
);

final signInRes = await Amplify.Auth.signIn(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,9 @@ void main() {
autoConfirm: true,
verifyAttributes: true,
enableMfa: enableMfa,
attributes: [
if (emailAlias)
AuthUserAttribute(
userAttributeKey: AuthUserAttributeKey.email,
value: username!,
),
],
attributes: {
if (emailAlias) AuthUserAttributeKey.email: username!,
},
);
if (emailAlias) {
expect(
Expand All @@ -84,7 +80,7 @@ void main() {
'as the username',
);
}
addTearDown(() async {
addTearDown(() {
username = null;
password = null;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,12 +328,9 @@ void main() {
password,
autoConfirm: true,
verifyAttributes: true,
attributes: [
AuthUserAttribute(
userAttributeKey: AuthUserAttributeKey.email,
value: originalEmail,
),
],
attributes: {
AuthUserAttributeKey.email: originalEmail,
},
);

final res = await Amplify.Auth.signIn(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,9 @@ void main() {
autoConfirm: true,
verifyAttributes: true,
enableMfa: true,
attributes: [
AuthUserAttribute(
userAttributeKey: AuthUserAttributeKey.phoneNumber,
value: username,
),
],
attributes: {
AuthUserAttributeKey.phoneNumber: username,
},
);

final code = await getOtpCode(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import 'get_current_user_test.dart' as get_current_user_tests;
import 'hosted_ui_webview_test.dart' as hosted_ui_webview_tests;
import 'hub_events_test.dart' as hub_events_tests;
import 'mfa_sms_test.dart' as mfa_sms_tests;
import 'mfa_sms_totp_optional_test.dart' as mfa_sms_totp_optional_tests;
import 'mfa_sms_totp_required_test.dart' as mfa_sms_totp_required_tests;
import 'mfa_totp_optional_test.dart' as mfa_totp_optional_tests;
import 'mfa_totp_required_test.dart' as mfa_totp_required_tests;
import 'native_auth_bridge_test.dart' as native_auth_bridge_tests;
import 'reset_password_test.dart' as reset_password_tests;
import 'security_test.dart' as security_tests;
Expand Down Expand Up @@ -44,6 +48,10 @@ void main() async {
hosted_ui_webview_tests.main();
hub_events_tests.main();
mfa_sms_tests.main();
mfa_sms_totp_optional_tests.main();
mfa_sms_totp_required_tests.main();
mfa_totp_optional_tests.main();
mfa_totp_required_tests.main();
native_auth_bridge_tests.main();
reset_password_tests.main();
security_tests.main();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,173 @@
import 'package:amplify_auth_integration_test/amplify_auth_integration_test.dart';
import 'package:amplify_flutter/amplify_flutter.dart';
import 'package:amplify_integration_test/amplify_integration_test.dart';
import 'package:checks/checks.dart';
import 'package:flutter_test/flutter_test.dart';

import 'test_runner.dart';

void main() {
testRunner.setupTests();

group(
'MFA (SMS)',
() {
setUp(() async {
await testRunner.configure();
});
group('MFA (SMS)', () {
// final smsEnvironments = mfaEnvironments.where((env) => env.sms);
// for (final env in smsEnvironments) {
// testRunner.withEnvironment(env, () {
// asyncTest(
// 'can sign in with SMS MFA enabled by administrator',
// (_) async {
// final username = generateUsername();
// final password = generatePassword();

// final otpResult =
// await getOtpCode(UserAttribute.username(username));

// await adminCreateUser(
// username,
// password,
// autoConfirm: true,
// verifyAttributes: true,
// enableMfa: true,
// );

// final signInRes = await Amplify.Auth.signIn(
// username: username,
// password: password,
// );
// check(signInRes.nextStep.signInStep)
// .equals(AuthSignInStep.confirmSignInWithSmsMfaCode);

// final confirmRes = await Amplify.Auth.confirmSignIn(
// confirmationValue: await otpResult.code,
// );
// check(confirmRes.nextStep.signInStep).equals(AuthSignInStep.done);

asyncTest('can sign in with SMS MFA', (_) async {
// check(await cognitoPlugin.fetchMfaPreference()).equals(
// const UserMfaPreference(
// enabled: {MfaType.sms},
// preferred: MfaType.sms,
// ),
// );
// },
// );
// });
// }

testRunner.withEnvironment(MfaEnvironment.mfaRequiredSms, () {
asyncTest('must configure MFA when required', (_) async {
final username = generateUsername();
final password = generatePassword();

final otpResult = await getOtpCode(UserAttribute.username(username));

await adminCreateUser(
username,
password,
autoConfirm: true,
verifyAttributes: true,
enableMfa: true,
);

final otpResult = await getOtpCode(UserAttribute.username(username));

final signInRes = await Amplify.Auth.signIn(
username: username,
password: password,
);
expect(
check(
signInRes.nextStep.signInStep,
AuthSignInStep.confirmSignInWithSmsMfaCode,
);
because: 'When MFA is required, it must be configured during '
'the first sign-in',
).equals(AuthSignInStep.confirmSignInWithSmsMfaCode);

final confirmRes = await Amplify.Auth.confirmSignIn(
confirmationValue: await otpResult.code,
);
expect(confirmRes.nextStep.signInStep, AuthSignInStep.done);
check(confirmRes.nextStep.signInStep).equals(AuthSignInStep.done);

check(await cognitoPlugin.fetchMfaPreference()).equals(
const UserMfaPreference(
enabled: {MfaType.sms},
preferred: MfaType.sms,
),
);

await check(
because:
'Interestingly, Cognito does not throw and allows it to be disabled.',
cognitoPlugin.updateMfaPreference(sms: MfaPreference.disabled),
).completes();
});
},
);
});

testRunner.withEnvironment(MfaEnvironment.mfaOptionalSms, () {
asyncTest('can skip configuring MFA when not required', (_) async {
final username = generateUsername();
final password = generatePassword();

await adminCreateUser(
username,
password,
autoConfirm: true,
verifyAttributes: true,
);

final signInRes = await Amplify.Auth.signIn(
username: username,
password: password,
);
check(
signInRes.nextStep.signInStep,
because: 'When MFA is not required, it can be skipped during '
'the first sign-in',
).equals(AuthSignInStep.done);

check(await cognitoPlugin.fetchMfaPreference())
.equals(const UserMfaPreference());
});

asyncTest(
'fetchMfaPreference returns SMS when enabled outside library',
(_) async {
final username = generateUsername();
final password = generatePassword();

await adminCreateUser(
username,
password,
autoConfirm: true,
verifyAttributes: true,
);

final signInRes = await Amplify.Auth.signIn(
username: username,
password: password,
);
check(
signInRes.nextStep.signInStep,
because: 'When MFA is not required, it can be skipped during '
'the first sign-in',
).equals(AuthSignInStep.done);

await adminEnableSmsMfa(username);

check(await cognitoPlugin.fetchMfaPreference()).equals(
const UserMfaPreference(
enabled: {MfaType.sms},
preferred: MfaType.sms,
),
);

await check(
because: 'SMS can be disabled when optional',
cognitoPlugin.updateMfaPreference(sms: MfaPreference.disabled),
).completes();

check(
because: 'Disabling SMS should mark it as not preferred',
await cognitoPlugin.fetchMfaPreference(),
).equals(
const UserMfaPreference(enabled: {}, preferred: null),
);
},
);
});
});
}
Loading

0 comments on commit 72f11e9

Please sign in to comment.