Skip to content

Commit

Permalink
switched to a different model of specifying domain
Browse files Browse the repository at this point in the history
  • Loading branch information
Niranjan Jayakar committed Apr 20, 2020
1 parent 5514d4e commit bc6d6d1
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 67 deletions.
18 changes: 15 additions & 3 deletions packages/@aws-cdk/aws-cognito/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -409,9 +409,21 @@ The following code sets up a user pool domain in Amazon Cognito hosted domain wi
```ts
const pool = new UserPool(this, 'Pool');
pool.addDomain('domain', {
cognitoDomainPrefix: 'my-awesome-app',
domain: UserPoolDomainType.cognitoDomain({
domainPrefix: 'my-awesome-app',
}),
});
```

The `UserPoolDomain` construct exposes a `cloudFrontDomainName` attribute that returns the CloudFront domain name. This
can then be used to wire it up with a CloudFront distribution or to a Route53 target.
On the other hand, the following code sets up a user pool domain and use your own custom domain -

```ts
const domainCert = new acm.Certificate.fromCertificateArn(this, 'domainCert', certificateArn);
const pool = new UserPool(this, 'Pool');
pool.addDomain('domain', {
domain: UserPoolDomainType.customDomain({
domainPrefix: 'my-awesome-app',
certificate: domainCert,
}),
});
```
65 changes: 46 additions & 19 deletions packages/@aws-cdk/aws-cognito/lib/user-pool-domain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,25 +44,60 @@ export interface CognitoDomainOptions {
readonly domainPrefix: string;
}

interface UserPoolDomainTypeConfig {
readonly domain: string;

readonly certificate?: ICertificate;
}

/**
* Options to create a UserPoolDomain
* The type of user pool domain. Two types are currently supported - custom domain and cognito domain.
*/
export interface UserPoolDomainOptions {
export class UserPoolDomainType {
/**
* Associate a custom domain with your user pool
* @see https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-add-custom-domain.html
* One of, and only one of, `customDomain` and `cognitoDomain` can be specified.
* @default - none
*/
readonly customDomain?: CustomDomainOptions;
public static customDomain(options: CustomDomainOptions): UserPoolDomainType {
return new UserPoolDomainType({
domain: options.domainName,
certificate: options.certificate,
});
}

/**
* Associate a cognito prefix domain with your user pool
* @see https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-assign-domain-prefix.html
* One of, and only one of, `customDomain` and `cognitoDomain` can be specified.
* @default - none.
*/
readonly cognitoDomain?: CognitoDomainOptions;
public static cognitoDomain(options: CognitoDomainOptions): UserPoolDomainType {
if (options.domainPrefix && !/^[a-z0-9-]+$/.test(options.domainPrefix)) {
throw new Error('domainPrefix for cognitoDomain can contain only lowercase alphabets, numbers and hyphens');
}
return new UserPoolDomainType({
domain: options.domainPrefix,
});
}

private constructor(private readonly domainConfig: UserPoolDomainTypeConfig) {}

/**
* @internal
*/
public _domainConfig(): UserPoolDomainTypeConfig {
return this.domainConfig;
}
}

/**
* Options to create a UserPoolDomain
*/
export interface UserPoolDomainOptions {
/**
* Domain configuration options for the two types of user pool domains.
* Create a cognito prefix domain via `UserPoolDomainType.cognitoPrefixDomain()` or,
* a custom domain via `UserPoolDomainType.customDomain()`,
*/
readonly domain: UserPoolDomainType;
}

/**
Expand All @@ -84,19 +119,11 @@ export class UserPoolDomain extends Resource implements IUserPoolDomain {
constructor(scope: Construct, id: string, props: UserPoolDomainProps) {
super(scope, id);

if (!!props.cognitoDomain === !!props.customDomain) {
throw new Error('One, and only one, of cognitoDomain or customDomain must be specified');
}

if (props.cognitoDomain && !/^[a-z0-9-]+$/.test(props.cognitoDomain.domainPrefix)) {
throw new Error('domainPrefix for cognitoDomain can contain only lowercase alphabets, numbers and hyphens');
}

const domain = props.customDomain?.domainName ?? props.cognitoDomain?.domainPrefix!;
const domainConfig = props.domain._domainConfig();
const resource = new CfnUserPoolDomain(this, 'Resource', {
userPoolId: props.userPool.userPoolId,
domain,
customDomainConfig: props.customDomain ? { certificateArn: props.customDomain.certificate.certificateArn } : undefined,
domain: domainConfig.domain,
customDomainConfig: domainConfig.certificate ? { certificateArn: domainConfig.certificate.certificateArn } : undefined,
});

this.domainName = resource.ref;
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-cognito/lib/user-pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ export class UserPool extends Resource implements IUserPool {
* Associate a domain to this user pool.
* @see https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-assign-domain.html
*/
public addDomain(id: string, options?: UserPoolDomainOptions): UserPoolDomain {
public addDomain(id: string, options: UserPoolDomainOptions): UserPoolDomain {
return new UserPoolDomain(this, id, {
userPool: this,
...options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "integuserpooldomainUserPool1E764E19"
"sts:ExternalId": "integuserpooldomaincfdistUserPool17475E8A"
}
},
"Effect": "Allow",
Expand Down Expand Up @@ -46,7 +46,7 @@
"EmailVerificationMessage": "Hello {username}, Your verification code is {####}",
"EmailVerificationSubject": "Verify your new account",
"SmsConfiguration": {
"ExternalId": "integuserpooldomainUserPool1E764E19",
"ExternalId": "integuserpooldomaincfdistUserPool17475E8A",
"SnsCallerArn": {
"Fn::GetAtt": [
"UserPoolsmsRole4EA729DD",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { App, CfnOutput, Stack } from '@aws-cdk/core';
import { UserPool } from '../lib';
import { UserPool, UserPoolDomainType } from '../lib';

/*
* Stack verification steps:
* * Verify that the CloudFrontDistribution stack output is of the format 'xxxxxxxxxxxxxx.cloudfront.net'
*/

const app = new App();
const stack = new Stack(app, 'integ-user-pool-domain');
const stack = new Stack(app, 'integ-user-pool-domain-cfdist');

const userpool = new UserPool(stack, 'UserPool');

const domain = userpool.addDomain('Domain', {
cognitoDomain: {
domain: UserPoolDomainType.cognitoDomain({
domainPrefix: 'cdk-integ-user-pool-domain'
}
}),
});

new CfnOutput(stack, 'Domain', {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Code, Function, IFunction, Runtime } from '@aws-cdk/aws-lambda';
import { App, CfnOutput, Duration, Stack } from '@aws-cdk/core';
import { BooleanAttribute, DateTimeAttribute, Mfa, NumberAttribute, StringAttribute, UserPool } from '../lib';
import { BooleanAttribute, DateTimeAttribute, Mfa, NumberAttribute, StringAttribute, UserPool, UserPoolDomainType } from '../lib';

const app = new App();
const stack = new Stack(app, 'integ-user-pool');
Expand Down Expand Up @@ -70,9 +70,9 @@ const userpool = new UserPool(stack, 'myuserpool', {
});

const cognitoDomain = userpool.addDomain('myuserpooldomain', {
cognitoDomain: {
domain: UserPoolDomainType.cognitoDomain({
domainPrefix: 'myawesomeapp'
}
}),
});

new CfnOutput(stack, 'userpoolId', {
Expand Down
48 changes: 13 additions & 35 deletions packages/@aws-cdk/aws-cognito/test/user-pool-domain.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import '@aws-cdk/assert/jest';
import { Certificate } from '@aws-cdk/aws-certificatemanager';
import { Stack } from '@aws-cdk/core';
import { UserPool, UserPoolDomain } from '../lib';
import { UserPool, UserPoolDomain, UserPoolDomainType } from '../lib';

describe('User Pool Client', () => {
test('custom domain name', () => {
Expand All @@ -14,10 +14,10 @@ describe('User Pool Client', () => {
'arn:aws:acm:eu-west-1:0123456789:certificate/7ec3e4ac-808a-4649-b805-66ae02346ad8');
new UserPoolDomain(stack, 'Domain', {
userPool: pool,
customDomain: {
domain: UserPoolDomainType.customDomain({
domainName: 'test-domain.example.com',
certificate,
}
}),
});

// THEN
Expand All @@ -38,9 +38,9 @@ describe('User Pool Client', () => {
// WHEN
new UserPoolDomain(stack, 'Domain', {
userPool: pool,
cognitoDomain: {
domain: UserPoolDomainType.cognitoDomain({
domainPrefix: 'cognito-domain-prefix'
}
}),
});

// THEN
Expand All @@ -50,37 +50,15 @@ describe('User Pool Client', () => {
});
});

test('fails when both customDomain and cognitoDomain are specified', () => {
const stack = new Stack();
const pool = new UserPool(stack, 'Pool');
const certificate = Certificate.fromCertificateArn(stack, 'cert',
'arn:aws:acm:eu-west-1:0123456789:certificate/7ec3e4ac-808a-4649-b805-66ae02346ad8');

expect(() => pool.addDomain('Domain', {
cognitoDomain: { domainPrefix: 'cognito-domain-prefix' },
customDomain: { domainName: 'test-domain.example.com', certificate },
})).toThrow(/cognitoDomain or customDomain/);
});

test('fails when neither customDomain nor cognitoDomain are specified', () => {
const stack = new Stack();
const pool = new UserPool(stack, 'Pool');

expect(() => pool.addDomain('Domain')).toThrow(/cognitoDomain or customDomain/);
});

test('fails when domainPrefix has characters outside the allowed charset', () => {
const stack = new Stack();
const pool = new UserPool(stack, 'Pool');

expect(() => pool.addDomain('Domain1', {
cognitoDomain: { domainPrefix: 'domain.prefix' }
expect(() => UserPoolDomainType.cognitoDomain({
domainPrefix: 'domain.prefix'
})).toThrow(/lowercase alphabets, numbers and hyphens/);
expect(() => pool.addDomain('Domain2', {
cognitoDomain: { domainPrefix: 'Domain-Prefix' }
expect(() => UserPoolDomainType.cognitoDomain({
domainPrefix: 'Domain-Prefix'
})).toThrow(/lowercase alphabets, numbers and hyphens/);
expect(() => pool.addDomain('Domain3', {
cognitoDomain: { domainPrefix: 'dómäin-prefix' }
expect(() => UserPoolDomainType.cognitoDomain({
domainPrefix: 'dómäin-prefix'
})).toThrow(/lowercase alphabets, numbers and hyphens/);
});

Expand All @@ -89,9 +67,9 @@ describe('User Pool Client', () => {
const stack = new Stack();
const pool = new UserPool(stack, 'Pool');
const domain = pool.addDomain('Domain', {
cognitoDomain: {
domain: UserPoolDomainType.cognitoDomain({
domainPrefix: 'cognito-domain-prefix',
}
}),
});

// WHEN
Expand Down

0 comments on commit bc6d6d1

Please sign in to comment.