Description
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.