aws-cognito: UserPoolDomain: User pool should have a custom domain associated, failed to update the certificate (Service: AWSCognitoIdentityProviderService)
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### Describe the bug
Upgrading from a legacy CDK `1.x` stack, to the latest `1.x` version (`1.202.0`), and now to the latest `2.x` version (`2.80.0`)
Previously I used my own custom resource for ensuring a custom domain was set on my `UserPool`, but in the process of upgrading, I have switched to using `UserPoolDomain`:
- https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cognito.UserPoolDomain.html
- https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cognito.CustomDomainOptions.html
I have also switched from the deprecated `DnsValidatedCertificate` to it's modern recommendation `Certificate`:
- https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_certificatemanager.DnsValidatedCertificate.html
- https://docs.aws.amazon.com/cdk/api/latest/docs/aws-cdk-lib.aws_certificatemanager.Certificate.html
- https://docs.aws.amazon.com/cdk/api/latest/docs/aws-cdk-lib.aws_certificatemanager.CertificateValidation.html
While trying to deploy my stack, I am getting the following error:
```
3:57:53 pm | UPDATE_FAILED | AWS::Cognito::UserPoolDomain | UserPoolDomain5479B217
User pool should have a custom domain associated, failed to update the certificate. (Service: AWSCognitoIdentityProviderService; Status Code: 400; Error Code:
InvalidParameterException; Request ID: 7468c635-58fe-4ac5-b907-d0eaddea3ca1; Proxy: null)
```
Which doesn't show up as any of these common errors/solutions:
- https://repost.aws/knowledge-center/cognito-custom-domain-errors
The relevant snippets of my stack code are as follows:
```typescript
// ..snip..
const authDomain = `${authSubdomain}.${domain}`
// ..snip..
const zone = HostedZone.fromLookup(this, 'Zone', {
domainName: domain,
})
const certificate = new Certificate(this, 'Certificate', {
domainName: authDomain,
validation: CertificateValidation.fromDns(zone),
})
// ..snip..
const userPool = new UserPool(this, 'UserPool', {
userPoolName: `${id}-UserPool`,
// ..snip..
}
const userPoolDomain = new UserPoolDomain(this, 'UserPoolDomain', {
userPool,
customDomain: {
domainName: authDomain,
certificate,
},
})
// Note that I also tried this, and it failed in the same way
// const userPoolDomain = userPool.addDomain('UserPoolDomain', {
// customDomain: {
// domainName: authDomain,
// certificate,
// },
// })
// ..snip..
new ARecord(this, 'UserPoolDomainAliasRecord', {
zone,
target: RecordTarget.fromAlias(new UserPoolDomainTarget(userPoolDomain)),
recordName: `${userPoolDomain.domainName}.`, // FQDN
})
// ..snip..
```
### Expected Behavior
CDK would correctly create my certificate, A record, and apply the custom domain to my Cognito User Pool
### Current Behavior
See error above
### Reproduction Steps
See details above
### Possible Solution
I'm not sure what the root cause of this is, but a random theory I had was that maybe the resources are trying to be created in the wrong order, which might be able to be fixed by using a 'DependsOn' or similar?
### Additional Information/Context
My previous custom resource/etc code looked like this:
```typescript
// ..snip..
const certificate = new DnsValidatedCertificate(this, 'Certificate', {
domainName: authDomain,
hostedZone: zone,
region: 'us-east-1',
})
// ..snip..
const userPoolDomain = new CfnUserPoolDomain(this, 'UserPoolDomain', {
userPoolId: userPool.userPoolId,
domain: authDomain,
customDomainConfig: {
certificateArn,
},
})
userPoolDomain.node.addDependency(userPool)
this._userPoolDomain = userPoolDomain.domain
// ..snip..
/**
* Use the AWS SDK to call get the CloudFrontDistribution with CognitoIdentityServiceProvider::describeUserPoolDomain
*
* @see https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_custom-resources.AwsCustomResource.html
* @see https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityServiceProvider.html#describeUserPoolDomain-property
*/
const describeCognitoUserPoolDomain = new AwsCustomResource(
this,
'DescribeCognitoUserPoolDomain',
{
resourceType: 'Custom::DescribeCognitoUserPoolDomain',
onCreate: {
region: 'us-east-1', // TODO: is this required?
service: 'CognitoIdentityServiceProvider',
action: 'describeUserPoolDomain',
parameters: {
Domain: userPoolDomain.domain,
},
physicalResourceId: PhysicalResourceId.of(userPoolDomain.domain),
},
policy: AwsCustomResourcePolicy.fromSdkCalls({
resources: AwsCustomResourcePolicy.ANY_RESOURCE,
}),
}
)
describeCognitoUserPoolDomain.node.addDependency(userPoolDomain)
const userPoolDomainDistribution = describeCognitoUserPoolDomain.getResponseField(
'DomainDescription.CloudFrontDistribution'
)
new CfnOutput(this, 'UserPoolDomainDistribution', {
value: userPoolDomainDistribution,
})
// ..snip..
new ARecord(this, 'UserPoolDomainAliasRecord', {
recordName: userPoolDomain.domain,
target: RecordTarget.fromAlias({
bind: () => ({
hostedZoneId: 'Z2FDTNDATAQYW2', // CloudFront Zone ID
dnsName: userPoolDomainDistribution,
}),
}),
zone,
})
```
See also:
- https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-add-custom-domain.html
### CDK CLI Version
2.80.0 (build bbdb16a)
### Framework Version
2.80.0
### Node.js Version
v16.15.1
### OS
macOS Ventura 13.3.1
### Language
Typescript
### Language Version
_No response_
### Other information
N/A
Contributor guide
Research direction
Start with the TypeScript stack entry points shown: Certificate, UserPoolDomain, UserPool, and the ARecord using UserPoolDomainTarget. Reproduce the deployment with the stated CDK 2.80.0 configuration, then trace the UserPoolDomain resource handling and dependency order. Done means the certificate, Cognito custom domain, and DNS record deploy successfully without the reported InvalidParameterException.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, typescript
- Domain
- cloud, infrastructure
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100