Describe the bug
In the us-gov-west-1 region, the Cognito Hosted UI always uses the fips endpoint (<domain-prefix>.auth-fips.<region>.amazoncognito.com). The UserPoolDomain.baseUrl function assumes the endpoint is always <prefix>.auth.<region>.amazoncognito.com. This results in a value that does not work in us-gov-west-1.
Expected Behavior
I expected calling baseUrl to return a URL that works in my current region.
Current Behavior
Calling baseUrl() returns a URL that does not work in us-gov-west-1.
Reproduction Steps
import 'source-map-support/register';
import * as cdk from "aws-cdk-lib";
import * as cognito from "aws-cdk-lib/aws-cognito";
const UNIQUE_PREFIX = "sample";
const app = new cdk.App();
const stack = new cdk.Stack(app, "DomainBroken");
const userPool = new cognito.UserPool(stack, "UserPool");
const domain = userPool.addDomain("domain", {
cognitoDomain: {
domainPrefix: UNIQUE_PREFIX,
},
});
new cdk.CfnOutput(stack, "Domain", { value: domain.baseUrl() });
Change the UNIQUE_PREFIX constant to actually contain a unique value and deploy this stack to us-gov-west-1 and try to navigate to the URL contained in the DomainBroken.Domain output. The name does not resolve.
Because I understand that not everyone has access to GovCloud, I have deployed a sample stack setting UNIQUE_PREFIX to govrepro. The CDK returns https://govrepro.auth.us-gov-west-1.amazoncognito.com; however, that does not resolve. https://govrepro.auth-fips.us-gov-west-1.amazoncognito.com does.
Possible Solution
Adding a parameter to baseUrl
This could be fixed by adding an optional fips?: boolean parameter to baseUrl (that defaults to false). The nice side effect here is that you'd be able to get FIPS URLs for Hosted UIs in US East/West and other regions that support it; the downside is that users may pass true in regions that do not support FIPS endpoints.
Code for adding FIPS parameter
diff --git a/packages/@aws-cdk/aws-cognito/lib/user-pool-domain.ts b/packages/@aws-cdk/aws-cognito/lib/user-pool-domain.ts
index b201b3153..a9859b7c5 100644
--- a/packages/@aws-cdk/aws-cognito/lib/user-pool-domain.ts
+++ b/packages/@aws-cdk/aws-cognito/lib/user-pool-domain.ts
@@ -152,10 +152,13 @@ export class UserPoolDomain extends Resource implements IUserPoolDomain {
/**
* The URL to the hosted UI associated with this domain
+ *
+ * @param fips whether to return the fips variant of the hosted UI
*/
- public baseUrl(): string {
+ public baseUrl(fips?: boolean): string {
if (this.isCognitoDomain) {
- return `https://${this.domainName}.auth.${Stack.of(this).region}.amazoncognito.com`;
+ const authBase = 'auth' + (fips ? '-fips' : '');
+ return `https://${this.domainName}.${authBase}.${Stack.of(this).region}.amazoncognito.com`;
}
return `https://${this.domainName}`;
}
Using a CfnCondition
Because this only impacts a single region (for now), it's possible baseUrl could return a CloudFormation condition but that scales poorly and adds a condition in the stack.
Code for using a CloudFormation condition
diff --git a/packages/@aws-cdk/aws-cognito/lib/user-pool-domain.ts b/packages/@aws-cdk/aws-cognito/lib/user-pool-domain.ts
index b201b3153..dc958f01f 100644
--- a/packages/@aws-cdk/aws-cognito/lib/user-pool-domain.ts
+++ b/packages/@aws-cdk/aws-cognito/lib/user-pool-domain.ts
@@ -1,5 +1,5 @@
import { ICertificate } from '@aws-cdk/aws-certificatemanager';
-import { IResource, Resource, Stack, Token } from '@aws-cdk/core';
+import { CfnCondition, Fn, IResource, Resource, Stack, Token } from '@aws-cdk/core';
import { AwsCustomResource, AwsCustomResourcePolicy, AwsSdkCall, PhysicalResourceId } from '@aws-cdk/custom-resources';
import { Construct } from 'constructs';
import { CfnUserPoolDomain } from './cognito.generated';
@@ -154,10 +154,17 @@ export class UserPoolDomain extends Resource implements IUserPoolDomain {
* The URL to the hosted UI associated with this domain
*/
public baseUrl(): string {
- if (this.isCognitoDomain) {
- return `https://${this.domainName}.auth.${Stack.of(this).region}.amazoncognito.com`;
+ if (!this.isCognitoDomain) {
+ return `https://${this.domainName}`;
}
- return `https://${this.domainName}`;
+ const isGovCondition = new CfnCondition(this, "IsGovWest", {
+ expression: Fn.conditionEquals(Stack.of(this).region, "us-gov-west-1")
+ });
+ return Fn.conditionIf(
+ isGovCondition.logicalId,
+ `https://${this.domainName}.auth-fips.${Stack.of(this).region}.amazoncognito.com`,
+ `https://${this.domainName}.auth.${Stack.of(this).region}.amazoncognito.com`
+ ).toString();
}
/**
Using region-info
This also feels like a good use case for a region-info in some ways, though, us-gov-west-1 is really the only "special" region I am aware of. The service is not yet available in other US government regions nor are User Pools available yet in aws-cn.
Adding Documentation
It would also be possible to just add documentation saying that the function doesn't work in GovCloud and to provide a workaround.
Documentation patch
diff --git a/packages/@aws-cdk/aws-cognito/lib/user-pool-domain.ts b/packages/@aws-cdk/aws-cognito/lib/user-pool-domain.ts
index b201b3153..5f71fdf25 100644
--- a/packages/@aws-cdk/aws-cognito/lib/user-pool-domain.ts
+++ b/packages/@aws-cdk/aws-cognito/lib/user-pool-domain.ts
@@ -152,6 +152,10 @@ export class UserPoolDomain extends Resource implements IUserPoolDomain {
/**
* The URL to the hosted UI associated with this domain
+ *
+ * The URL returned by this method will not work in us-gov-west-1 as it does not return
+ * a FIPS-compliant endpoint URL. Instead, build the URL manually using a format such as:
+ * `https://${domain.domainName}.auth-fips.${Stack.of(domain).region}.amazoncognito.com`.
*/
public baseUrl(): string {
if (this.isCognitoDomain) {
Additional Information/Context
The Amazon Cognito service in AWS GovCloud (US) does not support custom domains, so the only available option is a prefixed Cognito domain.
FIPS endpoints are available but not required in us-east-1, us-east-2, us-west-1, and us-west-2.
CDK CLI Version
2.22.0
Framework Version
No response
Node.js Version
16.14.1
OS
Fedora
Language
Typescript
Language Version
No response
Other information
I am happy to help implement a fix for this issue.
Describe the bug
In the
us-gov-west-1region, the Cognito Hosted UI always uses the fips endpoint (<domain-prefix>.auth-fips.<region>.amazoncognito.com). TheUserPoolDomain.baseUrlfunction assumes the endpoint is always<prefix>.auth.<region>.amazoncognito.com. This results in a value that does not work inus-gov-west-1.Expected Behavior
I expected calling
baseUrlto return a URL that works in my current region.Current Behavior
Calling
baseUrl()returns a URL that does not work inus-gov-west-1.Reproduction Steps
Change the
UNIQUE_PREFIXconstant to actually contain a unique value and deploy this stack tous-gov-west-1and try to navigate to the URL contained in theDomainBroken.Domainoutput. The name does not resolve.Because I understand that not everyone has access to GovCloud, I have deployed a sample stack setting
UNIQUE_PREFIXtogovrepro. The CDK returnshttps://govrepro.auth.us-gov-west-1.amazoncognito.com; however, that does not resolve.https://govrepro.auth-fips.us-gov-west-1.amazoncognito.comdoes.Possible Solution
Adding a parameter to
baseUrlThis could be fixed by adding an optional
fips?: booleanparameter tobaseUrl(that defaults to false). The nice side effect here is that you'd be able to get FIPS URLs for Hosted UIs in US East/West and other regions that support it; the downside is that users may passtruein regions that do not support FIPS endpoints.Code for adding FIPS parameter
Using a
CfnConditionBecause this only impacts a single region (for now), it's possible
baseUrlcould return a CloudFormation condition but that scales poorly and adds a condition in the stack.Code for using a CloudFormation condition
Using
region-infoThis also feels like a good use case for a
region-infoin some ways, though,us-gov-west-1is really the only "special" region I am aware of. The service is not yet available in other US government regions nor are User Pools available yet inaws-cn.Adding Documentation
It would also be possible to just add documentation saying that the function doesn't work in GovCloud and to provide a workaround.
Documentation patch
Additional Information/Context
The Amazon Cognito service in AWS GovCloud (US) does not support custom domains, so the only available option is a prefixed Cognito domain.
FIPS endpoints are available but not required in
us-east-1,us-east-2,us-west-1, andus-west-2.CDK CLI Version
2.22.0
Framework Version
No response
Node.js Version
16.14.1
OS
Fedora
Language
Typescript
Language Version
No response
Other information
I am happy to help implement a fix for this issue.