Skip to content

Commit

Permalink
Merge branch 'main' into connectableComputeEnvironment
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Aug 5, 2022
2 parents 7a70ff8 + 67a24ba commit 375d4b7
Show file tree
Hide file tree
Showing 55 changed files with 14,184 additions and 249 deletions.
14 changes: 14 additions & 0 deletions packages/@aws-cdk/aws-cognito/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,20 @@ pool.addClient('app-client', {
});
```

User Pool clients can generate a client ID as well as a client secret, to support more advanced authentication workflows.

To create a client with an autogenerated client secret, pass the `generateSecret: true` prop:

```ts
const userPoolClient = new cognito.UserPoolClient(this, 'UserPoolClient', {
userPool: importedPool,
generateSecret: true,
});

// Allows you to pass the generated secret to other pieces of infrastructure
const secret = userPoolClient.userPoolClientSecret;
```

### Resource Servers

A resource server is a server for access-protected resources. It handles authenticated requests from an app that has an
Expand Down
56 changes: 55 additions & 1 deletion packages/@aws-cdk/aws-cognito/lib/user-pool-client.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { IResource, Resource, Duration } from '@aws-cdk/core';
import { IResource, Resource, Duration, Stack, SecretValue } from '@aws-cdk/core';
import { AwsCustomResource, AwsCustomResourcePolicy, PhysicalResourceId } from '@aws-cdk/custom-resources';
import { Construct } from 'constructs';
import { CfnUserPoolClient } from './cognito.generated';
import { IUserPool } from './user-pool';
Expand Down Expand Up @@ -321,24 +322,39 @@ export interface IUserPoolClient extends IResource {
* @attribute
*/
readonly userPoolClientId: string;

/**
* The generated client secret. Only available if the "generateSecret" props is set to true
* @attribute
*/
readonly userPoolClientSecret: SecretValue;
}

/**
* Define a UserPool App Client
*/
export class UserPoolClient extends Resource implements IUserPoolClient {

/**
* Import a user pool client given its id.
*/
public static fromUserPoolClientId(scope: Construct, id: string, userPoolClientId: string): IUserPoolClient {
class Import extends Resource implements IUserPoolClient {
public readonly userPoolClientId = userPoolClientId;
get userPoolClientSecret(): SecretValue {
throw new Error('UserPool Client Secret is not available for imported Clients');
}
}

return new Import(scope, id);
}

public readonly userPoolClientId: string;

private _generateSecret?: boolean;
private readonly userPool: IUserPool;
private _userPoolClientSecret?: SecretValue;

/**
* The OAuth flows enabled for this client.
*/
Expand Down Expand Up @@ -374,6 +390,9 @@ export class UserPoolClient extends Resource implements IUserPoolClient {
}
}

this._generateSecret = props.generateSecret;
this.userPool = props.userPool;

const resource = new CfnUserPoolClient(this, 'Resource', {
clientName: props.userPoolClientName,
generateSecret: props.generateSecret,
Expand Down Expand Up @@ -407,6 +426,41 @@ export class UserPoolClient extends Resource implements IUserPoolClient {
return this._userPoolClientName;
}

public get userPoolClientSecret(): SecretValue {
if (!this._generateSecret) {
throw new Error(
'userPoolClientSecret is available only if generateSecret is set to true.',
);
}

// Create the Custom Resource that assists in resolving the User Pool Client secret
// just once, no matter how many times this method is called
if (!this._userPoolClientSecret) {
this._userPoolClientSecret = SecretValue.resourceAttribute(new AwsCustomResource(
this,
'DescribeCognitoUserPoolClient',
{
resourceType: 'Custom::DescribeCognitoUserPoolClient',
onCreate: {
region: Stack.of(this).region,
service: 'CognitoIdentityServiceProvider',
action: 'describeUserPoolClient',
parameters: {
UserPoolId: this.userPool.userPoolId,
ClientId: this.userPoolClientId,
},
physicalResourceId: PhysicalResourceId.of(this.userPoolClientId),
},
policy: AwsCustomResourcePolicy.fromSdkCalls({
resources: [this.userPool.userPoolArn],
}),
},
).getResponseField('UserPoolClient.ClientSecret'));
}

return this._userPoolClientSecret;
}

private configureAuthFlows(props: UserPoolClientProps): string[] | undefined {
if (!props.authFlows || Object.keys(props.authFlows).length === 0) return undefined;

Expand Down
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-cognito/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
},
"dependencies": {
"@aws-cdk/aws-certificatemanager": "0.0.0",
"@aws-cdk/aws-secretsmanager": "0.0.0",
"@aws-cdk/aws-iam": "0.0.0",
"@aws-cdk/aws-kms": "0.0.0",
"@aws-cdk/aws-lambda": "0.0.0",
Expand All @@ -102,6 +103,7 @@
"homepage": "https://github.com/aws/aws-cdk",
"peerDependencies": {
"@aws-cdk/aws-certificatemanager": "0.0.0",
"@aws-cdk/aws-secretsmanager": "0.0.0",
"@aws-cdk/aws-iam": "0.0.0",
"@aws-cdk/aws-kms": "0.0.0",
"@aws-cdk/aws-lambda": "0.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Secret } from '@aws-cdk/aws-secretsmanager';
import { App, RemovalPolicy, Stack } from '@aws-cdk/core';
import { OAuthScope, UserPool, ClientAttributes, StringAttribute } from '../lib';
import { ClientAttributes, OAuthScope, StringAttribute, UserPool } from '../lib';

const app = new App();
const stack = new Stack(app, 'integ-user-pool-client-explicit-props');
Expand All @@ -12,7 +13,7 @@ const userpool = new UserPool(stack, 'myuserpool', {
},
});

userpool.addClient('myuserpoolclient', {
const client = userpool.addClient('myuserpoolclient', {
userPoolClientName: 'myuserpoolclient',
authFlows: {
adminUserPassword: true,
Expand Down Expand Up @@ -57,3 +58,7 @@ userpool.addClient('myuserpoolclient', {
website: true,
}).withCustomAttributes('attribute_one', 'attribute_two'),
});

new Secret(stack, 'Secret', {
secretStringValue: client.userPoolClientSecret,
});
Loading

0 comments on commit 375d4b7

Please sign in to comment.