Skip to content

Commit

Permalink
Revert "Revert "feat(amplify-category-auth): use EnabledMFAs to only …
Browse files Browse the repository at this point in the history
…configure TOTP (#7779)" (#7790)" (#7971)

This reverts commit fa172c4.
  • Loading branch information
ammarkarachi committed Oct 26, 2021
1 parent 8a12868 commit ff418d1
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<% var autoVerifiedAttributes = props.autoVerifiedAttributes ? props.autoVerifiedAttributes.concat(props.aliasAttributes ? props.aliasAttributes : []).filter((attr, i, aliasAttributeArray) => ['email', 'phone_number'].includes(attr) && aliasAttributeArray.indexOf(attr) === i) : [] %>
<% var configureSMS = ((props.autoVerifiedAttributes && props.autoVerifiedAttributes.includes('phone_number')) || (props.mfaConfiguration != 'OFF' && props.mfaTypes && props.mfaTypes.includes('SMS Text Message')) || (props.requiredAttributes && props.requiredAttributes.includes('phone_number'))) %>
AWSTemplateFormatVersion: 2010-09-09

Parameters:
Expand Down Expand Up @@ -78,6 +79,7 @@ Resources:
MaxAge: 3000
<% } %>
<%if (props.authSelections !== 'identityPoolOnly') { %>
<% if(!props.useEnabledMfas || configureSMS) { %>
# BEGIN SNS ROLE RESOURCE
SNSRole:
# Created to allow the UserPool SMS Config to publish via the Simple Notification Service during MFA Process
Expand Down Expand Up @@ -107,6 +109,7 @@ Resources:
Action:
- "sns:Publish"
Resource: "*"
<% } %>
# BEGIN USER POOL RESOURCES
UserPool:
# Created upon user selection
Expand Down Expand Up @@ -182,12 +185,23 @@ Resources:
AliasAttributes: !Ref aliasAttributes
<% } %>
MfaConfiguration: !Ref mfaConfiguration
<% if(props.useEnabledMfas && props.mfaConfiguration != 'OFF') {%>
EnabledMfas:
<% if(configureSMS) {%>
- SMS_MFA
<% } %>
<% if(props.mfaTypes.includes('TOTP')) {%>
- SOFTWARE_TOKEN_MFA
<% } %>
<% } %>
<% if(!props.useEnabledMfas || configureSMS) {%>
SmsVerificationMessage: !Ref smsVerificationMessage
SmsAuthenticationMessage: !Ref smsAuthenticationMessage
SmsConfiguration:
SnsCallerArn: !GetAtt SNSRole.Arn
ExternalId: <%=`${props.resourceNameTruncated}_role_external_id`%>
<%if (props.mfaConfiguration != 'OFF') { %>
<% } %>
<%if (configureSMS) { %>
DependsOn: SNSRole
<% } %>
<%if (!props.breakCircularDependency && props.triggers && props.dependsOn) { %>
Expand Down Expand Up @@ -818,7 +832,7 @@ Resources:
DependsOn: OAuthCustomResourceLogPolicy
<% } %>
<%if (props.mfaConfiguration != 'OFF') { %>
<%if (!props.useEnabledMfas && props.mfaConfiguration != 'OFF') { %>
# BEGIN MFA LAMBDA RESOURCES
MFALambdaRole:
# Created to execute Lambda which sets MFA config values
Expand Down Expand Up @@ -1208,7 +1222,7 @@ Outputs :
AppClientSecret:
Value: !GetAtt UserPoolClientInputs.appSecret
Condition: ShouldOutputAppClientSecrets
<%if (props.mfaConfiguration != 'OFF') { %>
<%if (!props.useEnabledMfas || configureSMS) { %>
CreatedSNSRole:
Value: !GetAtt SNSRole.Arn
Description: role arn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface ServiceQuestionsBaseResult {
userpoolClientReadAttributes: string[];
userpoolClientWriteAttributes: string[];
usernameCaseSensitive?: boolean;
useEnabledMfas?: boolean;
authTriggerConnections?: string;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ export const getAddAuthDefaultsApplier = (context: any, defaultValuesFilename: s
if (FeatureFlags.getBoolean('auth.enableCaseInsensitivity')) {
result.usernameCaseSensitive = false;
}
// If the feature flag is enabled the MFA TOTP can only be enabled

result.useEnabledMfas = FeatureFlags.getBoolean('auth.useEnabledMfas');

/* merge actual answers object into props object,
* ensuring that manual entries override defaults */
Expand Down
6 changes: 6 additions & 0 deletions packages/amplify-cli-core/src/feature-flags/featureFlags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,12 @@ export class FeatureFlags {
defaultValueForExistingProjects: false,
defaultValueForNewProjects: false,
},
{
name: 'useEnabledMfas',
type: 'boolean',
defaultValueForExistingProjects: false,
defaultValueForNewProjects: true,
},
]);

this.registerFlag('codegen', [
Expand Down
8 changes: 8 additions & 0 deletions packages/amplify-e2e-core/src/utils/sdk-calls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,14 @@ export const getUserPool = async (userpoolId, region) => {
return res;
};

export const getMFAConfiguration = async (
userPoolId: string,
region: string,
): Promise<CognitoIdentityServiceProvider.GetUserPoolMfaConfigResponse> => {
config.update({ region });
return await new CognitoIdentityServiceProvider().getUserPoolMfaConfig({ UserPoolId: userPoolId }).promise();
};

export const getLambdaFunction = async (functionName: string, region: string) => {
const lambda = new Lambda({ region });
try {
Expand Down
102 changes: 101 additions & 1 deletion packages/amplify-e2e-tests/src/__tests__/auth_5.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import {
headlessAuthImport,
} from 'amplify-e2e-core';
import { addAuthWithDefault, getBackendAmplifyMeta } from 'amplify-e2e-core';
import { createNewProjectDir, deleteProjectDir, getProjectMeta, getUserPool } from 'amplify-e2e-core';
import { createNewProjectDir, deleteProjectDir, getProjectMeta, getUserPool, getMFAConfiguration } from 'amplify-e2e-core';
import {
AddAuthRequest,
CognitoUserPoolSigninMethod,
CognitoPasswordRecoveryConfiguration,
CognitoUserProperty,
ImportAuthRequest,
UpdateAuthRequest,
Expand Down Expand Up @@ -65,6 +66,105 @@ describe('headless auth', () => {
const userPool = await getUserPool(id, meta.providers.awscloudformation.Region);
expect(userPool.UserPool).toBeDefined();
});
it('adds auth resource with TOTP only', async () => {
const addAuthRequest: AddAuthRequest = {
version: 1,
resourceName: 'myAuthResource',
serviceConfiguration: {
serviceName: 'Cognito',
includeIdentityPool: false,
userPoolConfiguration: {
requiredSignupAttributes: [CognitoUserProperty.EMAIL],
signinMethod: CognitoUserPoolSigninMethod.PHONE_NUMBER,
mfa: {
mode: 'OPTIONAL',
mfaTypes: ['TOTP'],
smsMessage: 'The verification code is',
},
},
},
};

await initJSProjectWithProfile(projRoot, defaultsSettings);
await addHeadlessAuth(projRoot, addAuthRequest);
await amplifyPushAuth(projRoot);
const meta = getProjectMeta(projRoot);
const id = Object.keys(meta.auth).map(key => meta.auth[key])[0].output.UserPoolId;
const region = meta.providers.awscloudformation.Region;
const userPool = await getUserPool(id, meta.providers.awscloudformation.Region);
const mfaconfig = await getMFAConfiguration(id, region);
expect(mfaconfig.SoftwareTokenMfaConfiguration.Enabled).toBeTruthy();
expect(mfaconfig.SmsMfaConfiguration).toBeUndefined();
expect(userPool.UserPool).toBeDefined();
});

it('adds auth resource with TOTP only but enable SMS through signUp Attributes', async () => {
const addAuthRequest: AddAuthRequest = {
version: 1,
resourceName: 'myAuthResource',
serviceConfiguration: {
serviceName: 'Cognito',
includeIdentityPool: false,
userPoolConfiguration: {
requiredSignupAttributes: [CognitoUserProperty.EMAIL, CognitoUserProperty.PHONE_NUMBER],
signinMethod: CognitoUserPoolSigninMethod.PHONE_NUMBER,
mfa: {
mode: 'OPTIONAL',
mfaTypes: ['TOTP'],
smsMessage: 'The verification code is {####}',
},
},
},
};

await initJSProjectWithProfile(projRoot, defaultsSettings);
await addHeadlessAuth(projRoot, addAuthRequest);
await amplifyPushAuth(projRoot);
const meta = getProjectMeta(projRoot);
const id = Object.keys(meta.auth).map(key => meta.auth[key])[0].output.UserPoolId;
const region = meta.providers.awscloudformation.Region;
const userPool = await getUserPool(id, meta.providers.awscloudformation.Region);
const mfaconfig = await getMFAConfiguration(id, region);
expect(mfaconfig.SoftwareTokenMfaConfiguration.Enabled).toBeTruthy();
expect(mfaconfig.SmsMfaConfiguration.SmsConfiguration).toBeDefined();
expect(userPool.UserPool).toBeDefined();
});

it('adds auth resource with TOTP only but enables SMS through password recovery', async () => {
const addAuthRequest: AddAuthRequest = {
version: 1,
resourceName: 'myAuthResource',
serviceConfiguration: {
serviceName: 'Cognito',
includeIdentityPool: false,
userPoolConfiguration: {
requiredSignupAttributes: [CognitoUserProperty.EMAIL],
passwordRecovery: {
deliveryMethod: 'SMS',
smsMessage: 'The verification code is {####}',
},
signinMethod: CognitoUserPoolSigninMethod.PHONE_NUMBER,
mfa: {
mode: 'OPTIONAL',
mfaTypes: ['TOTP'],
smsMessage: 'The verification code is {####}',
},
},
},
};

await initJSProjectWithProfile(projRoot, defaultsSettings);
await addHeadlessAuth(projRoot, addAuthRequest);
await amplifyPushAuth(projRoot);
const meta = getProjectMeta(projRoot);
const id = Object.keys(meta.auth).map(key => meta.auth[key])[0].output.UserPoolId;
const region = meta.providers.awscloudformation.Region;
const userPool = await getUserPool(id, meta.providers.awscloudformation.Region);
const mfaconfig = await getMFAConfiguration(id, region);
expect(mfaconfig.SoftwareTokenMfaConfiguration.Enabled).toBeTruthy();
expect(mfaconfig.SmsMfaConfiguration.SmsConfiguration).toBeDefined();
expect(userPool.UserPool).toBeDefined();
});

it('updates existing auth resource', async () => {
const updateAuthRequest: UpdateAuthRequest = {
Expand Down

0 comments on commit ff418d1

Please sign in to comment.