Skip to content

Commit

Permalink
feat(cognito-userpool): Add mfaMessage option
Browse files Browse the repository at this point in the history
This commit adds a new, optional `mfaMessage` to
Cognito UserPools.
  • Loading branch information
cjihrig committed Apr 18, 2021
1 parent 8a949dc commit 2b46380
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 1 deletion.
25 changes: 25 additions & 0 deletions packages/@aws-cdk/aws-cognito/lib/user-pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,12 @@ export interface UserPoolProps {
*/
readonly mfa?: Mfa;

/**
* A string representing the MFA message.
* @default - Omitted by default.
*/
readonly mfaMessage?: string;

/**
* Configure the MFA types that users can use in this user pool. Ignored if `mfa` is set to `OFF`.
*
Expand Down Expand Up @@ -761,6 +767,7 @@ export class UserPool extends UserPoolBase {
aliasAttributes: signIn.aliasAttrs,
autoVerifiedAttributes: signIn.autoVerifyAttrs,
lambdaConfig: Lazy.any({ produce: () => undefinedIfNoKeys(this.triggers) }),
smsAuthenticationMessage: this.mfaMessage(props),
smsConfiguration: this.smsConfiguration(props),
adminCreateUserConfig,
emailVerificationMessage,
Expand Down Expand Up @@ -810,6 +817,24 @@ export class UserPool extends UserPoolBase {
});
}

private mfaMessage(props: UserPoolProps): string | undefined {
const CODE_TEMPLATE = '{####}';
const MAX_LENGTH = 140;
const message = props.mfaMessage;

if (message && !Token.isUnresolved(message)) {
if (!message.includes(CODE_TEMPLATE)) {
throw new Error(`MFA message must contain the template string '${CODE_TEMPLATE}'`);
}

if (message.length > MAX_LENGTH) {
throw new Error(`MFA message must be between ${CODE_TEMPLATE.length} and ${MAX_LENGTH} characters`);
}
}

return message;
}

private verificationMessageConfiguration(props: UserPoolProps): CfnUserPool.VerificationMessageTemplateProperty {
const CODE_TEMPLATE = '{####}';
const VERIFY_EMAIL_TEMPLATE = '{##Verify Email##}';
Expand Down
46 changes: 45 additions & 1 deletion packages/@aws-cdk/aws-cognito/test/user-pool.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ describe('User Pool', () => {
EmailSubject: 'Verify your new account',
SmsMessage: 'The verification code to your new account is {####}',
},
SmsAuthenticationMessage: ABSENT,
SmsConfiguration: ABSENT,
lambdaTriggers: ABSENT,
});
Expand Down Expand Up @@ -80,6 +81,49 @@ describe('User Pool', () => {
});
}),

test('mfa authentication message is configured correctly', () => {
// GIVEN
const stack = new Stack();
const message = 'The authentication code to your account is {####}';

// WHEN
new UserPool(stack, 'Pool', {
mfaMessage: message,
});

// THEN
expect(stack).toHaveResourceLike('AWS::Cognito::UserPool', {
SmsAuthenticationMessage: message,
});
}),

test('mfa authentication message is validated', () => {
const stack = new Stack();

expect(() => new UserPool(stack, 'Pool1', {
mfaMessage: '{####',
})).toThrow(/MFA message must contain the template string/);

expect(() => new UserPool(stack, 'Pool2', {
mfaMessage: '{####}',
})).not.toThrow();

expect(() => new UserPool(stack, 'Pool3', {
mfaMessage: `{####}${'x'.repeat(135)}`,
})).toThrow(/MFA message must be between 6 and 140 characters/);

expect(() => new UserPool(stack, 'Pool4', {
mfaMessage: `{####}${'x'.repeat(134)}`,
})).not.toThrow();

// Validation is skipped for tokens.
const parameter = new CfnParameter(stack, 'Parameter');

expect(() => new UserPool(stack, 'Pool5', {
mfaMessage: parameter.valueAsString,
})).not.toThrow();
});

test('email and sms verification messages are validated', () => {
const stack = new Stack();

Expand Down Expand Up @@ -1355,4 +1399,4 @@ function fooFunction(scope: Construct, name: string): lambda.IFunction {
runtime: lambda.Runtime.NODEJS_12_X,
handler: 'index.handler',
});
}
}

0 comments on commit 2b46380

Please sign in to comment.