aws/aws-cdk

user pool - link style email verification fails to deploy

Closed this issue · 6 comments

Reported by @0xdevalias -

const userPool = new cognito.UserPool(this, 'UserPool', {
  // ..snip..

  userVerification: {
    emailSubject: 'Confirm your account on REDACTED',
    emailBody:
      'Hello {username}, welcome to REDACTED! Use the following link to verify your account: {####}',
    emailStyle: cognito.VerificationEmailStyle.LINK,
    smsMessage:
      'Hello {username}, welcome to REDACTED! Use the following code to verify your account: {####}',
  },

  // ..snip..
})

generates the following error -

1/3 | 8:50:23 PM | UPDATE_FAILED        | AWS::Cognito::UserPool                | UserPool (UserPool6BA7E5F2) The message is invalid. (Service: AWSCognitoIdentityProviderService; Status Code: 400; Error Code: InvalidParameterException; Request ID: c3ce01b4-a431-4475-82fd-fdc30fec3660)
	new UserPool (/Users/devalias/dev/REDACTED/packages/REDACTED-infrastructure/node_modules/@aws-cdk/aws-cognito/lib/user-pool.js:73:26)

If this is purely a feature request, are you able to explain what the correct parameters are for a 'link' styled template?

As best I could find on any of the AWS documentation for this feature, CloudFormation for it, etc, what I was using was correct, which makes me think this is a bug? (though i'm not actually sure what the underlying calls being made are/how to debug them to get better details)

@0xdevalias - Unfortunately, we plumb these messages straight down to Cognito and its the Cognito service that is generating this error, so it's currently not something the CDK controls or has information on.

My best guess, looking at this documentation, is that {####} is only for code verification, and you might have to use one of the other templates at the bottom of the document ({one-click-link-valid} maybe?).

You might have to contact support to get this information from the Cognito service.

@0xdevalias - Try putting {##Verify Email##} instead of {####}. This might work.

That makes sense.

I did try that {##Verify Email##} one (lifted from the console UI), but it then failed the regex that requires it to contain the {####} tag. I didn’t try the others though, that may be a good approach. Might also be able to just find a raw CloudFormation example for it and work backwards from there, or set the template in the UI then read it back from the API and see if that gives any clues.

Ok, so I set the 'LINK' type via the AWS Console UI, then read back the value using the CLI:

This is the relevant looking parts of the response:

{
        "SmsVerificationMessage": "Hello {username}, welcome to REDACTED! Use the following code to verify your account: {####}",
        "EmailVerificationMessage": "Hello {username},\n\nWelcome to REDACTED!\n\nUse the following code to verify your account: {####}",
        "EmailVerificationSubject": "Confirm your account on REDACTED",

        "VerificationMessageTemplate": {
            "SmsMessage": "Hello {username}, welcome to REDACTED! Use the following code to verify your account: {####}",
            "EmailMessage": "Hello {username},\n\nWelcome to REDACTED!\n\nUse the following code to verify your account: {####}",
            "EmailSubject": "Confirm your account on REDACTED",
            "EmailMessageByLink": "Hello {username},\n\nWelcome to REDACTED!\n\nPlease click the link below to verify your email account. {##Verify Email##} ",
            "EmailSubjectByLink": "Confirm your account on REDACTED",
            "DefaultEmailOption": "CONFIRM_WITH_LINK"
        },

        "AdminCreateUserConfig": {
            "AllowAdminCreateUserOnly": true,
            "UnusedAccountValidityDays": 5,
            "InviteMessageTemplate": {
                "SMSMessage": "Hello {username}, you have been invited to join REMDR! Your temporary password is: {####}",
                "EmailMessage": "Hello {username},\n\nYou have been invited to join REMDR!\n\nYour temporary password is: {####}",
                "EmailSubject": "Invitation to join REMDR"
            }
        }
}

So it would seem what we want to do this is AWS::Cognito::UserPool VerificationMessageTemplate section:

Sp my current workaround code looks like this:

const cfnUserPool = userPool.node.defaultChild

// https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cognito-userpool-verificationmessagetemplate.html
cfnUserPool.verificationMessageTemplate = {
  defaultEmailOption: 'CONFIRM_WITH_LINK',

  emailSubject: 'Confirm your account on REDACTED',
  emailSubjectByLink: 'Confirm your account on REDACTED',

  emailMessage: 'Hello {username},\n\nWelcome to REDACTED!\n\nPlease use the following code to verify your account: {####}',
  emailMessageByLink: 'Hello {username},\n\nWelcome to REDACTED!\n\nPlease use the following link to verify your account: {##Verify Email##}',
}

Which deployed successfully!

@0xdevalias - it seems to me that the correct thing to do here is to not set the EmailVerificationMessage and EmailVerificationSubject properties when the 'CONFIRM_WITH_LINK' option is used.

This would look like -

const cfnuserpool = userpool.node.defaultChild as CfnUserPool;
cfnuserpool.emailVerificationMessage = undefined;
cfnuserpool.emailVerificationSubject = undefined;

Can you check if this works for you, and sets up the user pool as you would expect?