Skip to content
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

feat(cognito): user pool - customize mfa message #14241

Merged
merged 4 commits into from
Jun 4, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
26 changes: 26 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,13 @@ export interface UserPoolProps {
*/
readonly mfa?: Mfa;

/**
* The SMS message template sent during MFA verification.
* Use '{####}' in the template where Cognito should insert the verification code.
* @default - 'Your authentication code is {####}.'
nija-at marked this conversation as resolved.
Show resolved Hide resolved
*/
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 +768,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 +818,24 @@ export class UserPool extends UserPoolBase {
});
}

private mfaMessage(props: UserPoolProps): string | undefined {
cjihrig marked this conversation as resolved.
Show resolved Hide resolved
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',
});
}
}