diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/README.md b/packages/@aws-cdk/aws-apigatewayv2-authorizers/README.md index df0a69a82b11e..d1aebb7477b82 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/README.md +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/README.md @@ -48,9 +48,9 @@ In the example below, all routes will require the `manage:books` scope present i ```ts import { HttpJwtAuthorizer } from '@aws-cdk/aws-apigatewayv2-authorizers'; -const authorizer = new HttpJwtAuthorizer({ +const issuer = 'https://test.us.auth0.com'; +const authorizer = new HttpJwtAuthorizer('DefaultAuthorizer', issuer, { jwtAudience: ['3131231'], - jwtIssuer: 'https://test.us.auth0.com', }); const api = new apigwv2.HttpApi(this, 'HttpApi', { @@ -73,9 +73,9 @@ The example below showcases default authorization, along with route authorizatio import { HttpJwtAuthorizer } from '@aws-cdk/aws-apigatewayv2-authorizers'; import { HttpUrlIntegration } from '@aws-cdk/aws-apigatewayv2-integrations'; -const authorizer = new HttpJwtAuthorizer({ +const issuer = 'https://test.us.auth0.com'; +const authorizer = new HttpJwtAuthorizer('DefaultAuthorizer', issuer, { jwtAudience: ['3131231'], - jwtIssuer: 'https://test.us.auth0.com', }); const api = new apigwv2.HttpApi(this, 'HttpApi', { @@ -130,9 +130,9 @@ Clients that fail authorization are presented with either 2 responses: import { HttpJwtAuthorizer } from '@aws-cdk/aws-apigatewayv2-authorizers'; import { HttpUrlIntegration } from '@aws-cdk/aws-apigatewayv2-integrations'; -const authorizer = new HttpJwtAuthorizer({ +const issuer = 'https://test.us.auth0.com'; +const authorizer = new HttpJwtAuthorizer('BooksAuthorizer', issuer, { jwtAudience: ['3131231'], - jwtIssuer: 'https://test.us.auth0.com', }); const api = new apigwv2.HttpApi(this, 'HttpApi'); @@ -158,12 +158,8 @@ import { HttpUserPoolAuthorizer } from '@aws-cdk/aws-apigatewayv2-authorizers'; import { HttpUrlIntegration } from '@aws-cdk/aws-apigatewayv2-integrations'; const userPool = new cognito.UserPool(this, 'UserPool'); -const userPoolClient = userPool.addClient('UserPoolClient'); -const authorizer = new HttpUserPoolAuthorizer({ - userPool, - userPoolClients: [userPoolClient], -}); +const authorizer = new HttpUserPoolAuthorizer('BooksAuthorizer', userPool); const api = new apigwv2.HttpApi(this, 'HttpApi'); @@ -188,10 +184,8 @@ import { HttpUrlIntegration } from '@aws-cdk/aws-apigatewayv2-integrations'; // This function handles your auth logic declare const authHandler: lambda.Function; -const authorizer = new HttpLambdaAuthorizer({ - authorizerName: 'lambda-authorizer', +const authorizer = new HttpLambdaAuthorizer('BooksAuthorizer', authHandler, { responseTypes: [HttpLambdaResponseType.SIMPLE], // Define if returns simple and/or iam response - handler: authHandler, }); const api = new apigwv2.HttpApi(this, 'HttpApi'); diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/lib/http/jwt.ts b/packages/@aws-cdk/aws-apigatewayv2-authorizers/lib/http/jwt.ts index 184d02f3382b6..94e4f1e230e62 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/lib/http/jwt.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/lib/http/jwt.ts @@ -5,7 +5,6 @@ import { HttpRouteAuthorizerConfig, IHttpRouteAuthorizer, } from '@aws-cdk/aws-apigatewayv2'; -import { Token } from '@aws-cdk/core'; /** * Properties to initialize HttpJwtAuthorizer. @@ -14,7 +13,7 @@ export interface HttpJwtAuthorizerProps { /** * The name of the authorizer - * @default 'JwtAuthorizer' + * @default - same value as `id` passed in the constructor */ readonly authorizerName?: string; @@ -30,11 +29,6 @@ export interface HttpJwtAuthorizerProps { * A valid JWT must provide an aud that matches at least one entry in this list. */ readonly jwtAudience: string[] - - /** - * The base domain of the identity provider that issues JWT. - */ - readonly jwtIssuer: string; } /** @@ -44,21 +38,27 @@ export interface HttpJwtAuthorizerProps { export class HttpJwtAuthorizer implements IHttpRouteAuthorizer { private authorizer?: HttpAuthorizer; - constructor(private readonly props: HttpJwtAuthorizerProps) { + /** + * Initialize a JWT authorizer to be bound with HTTP route. + * @param id The id of the underlying construct + * @param jwtIssuer The base domain of the identity provider that issues JWT + * @param props Properties to configure the authorizer + */ + constructor( + private readonly id: string, + private readonly jwtIssuer: string, + private readonly props: HttpJwtAuthorizerProps) { } public bind(options: HttpRouteAuthorizerBindOptions): HttpRouteAuthorizerConfig { if (!this.authorizer) { - const id = this.props.authorizerName && !Token.isUnresolved(this.props.authorizerName) ? - this.props.authorizerName : 'JwtAuthorizer'; - - this.authorizer = new HttpAuthorizer(options.scope, id, { + this.authorizer = new HttpAuthorizer(options.scope, this.id, { httpApi: options.route.httpApi, identitySource: this.props.identitySource ?? ['$request.header.Authorization'], type: HttpAuthorizerType.JWT, - authorizerName: this.props.authorizerName, + authorizerName: this.props.authorizerName ?? this.id, jwtAudience: this.props.jwtAudience, - jwtIssuer: this.props.jwtIssuer, + jwtIssuer: this.jwtIssuer, }); } diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/lib/http/lambda.ts b/packages/@aws-cdk/aws-apigatewayv2-authorizers/lib/http/lambda.ts index fcb4f327c08a2..2e56317c1a667 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/lib/http/lambda.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/lib/http/lambda.ts @@ -32,9 +32,10 @@ export enum HttpLambdaResponseType { export interface HttpLambdaAuthorizerProps { /** - * The name of the authorizer + * Friendly authorizer name + * @default - same value as `id` passed in the constructor. */ - readonly authorizerName: string; + readonly authorizerName?: string; /** * The identity source for which authorization is requested. @@ -43,11 +44,6 @@ export interface HttpLambdaAuthorizerProps { */ readonly identitySource?: string[]; - /** - * The lambda function used for authorization - */ - readonly handler: IFunction; - /** * How long APIGateway should cache the results. Max 1 hour. * Disable caching by setting this to `Duration.seconds(0)`. @@ -76,7 +72,16 @@ export class HttpLambdaAuthorizer implements IHttpRouteAuthorizer { private authorizer?: HttpAuthorizer; private httpApi?: IHttpApi; - constructor(private readonly props: HttpLambdaAuthorizerProps) { + /** + * Initialize a lambda authorizer to be bound with HTTP route. + * @param id The id of the underlying construct + * @param pool The lambda function handler to use for authorization + * @param props Properties to configure the authorizer + */ + constructor( + private readonly id: string, + private readonly handler: IFunction, + private readonly props: HttpLambdaAuthorizerProps = {}) { } public bind(options: HttpRouteAuthorizerBindOptions): HttpRouteAuthorizerConfig { @@ -85,26 +90,24 @@ export class HttpLambdaAuthorizer implements IHttpRouteAuthorizer { } if (!this.authorizer) { - const id = this.props.authorizerName; - const responseTypes = this.props.responseTypes ?? [HttpLambdaResponseType.IAM]; const enableSimpleResponses = responseTypes.includes(HttpLambdaResponseType.SIMPLE) || undefined; this.httpApi = options.route.httpApi; - this.authorizer = new HttpAuthorizer(options.scope, id, { + this.authorizer = new HttpAuthorizer(options.scope, this.id, { httpApi: options.route.httpApi, identitySource: this.props.identitySource ?? [ '$request.header.Authorization', ], type: HttpAuthorizerType.LAMBDA, - authorizerName: this.props.authorizerName, + authorizerName: this.props.authorizerName ?? this.id, enableSimpleResponses, payloadFormatVersion: enableSimpleResponses ? AuthorizerPayloadVersion.VERSION_2_0 : AuthorizerPayloadVersion.VERSION_1_0, - authorizerUri: lambdaAuthorizerArn(this.props.handler), + authorizerUri: lambdaAuthorizerArn(this.handler), resultsCacheTtl: this.props.resultsCacheTtl ?? Duration.minutes(5), }); - this.props.handler.addPermission(`${Names.nodeUniqueId(this.authorizer.node)}-Permission`, { + this.handler.addPermission(`${Names.nodeUniqueId(this.authorizer.node)}-Permission`, { scope: options.scope as CoreConstruct, principal: new ServicePrincipal('apigateway.amazonaws.com'), sourceArn: Stack.of(options.route).formatArn({ diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/lib/http/user-pool.ts b/packages/@aws-cdk/aws-apigatewayv2-authorizers/lib/http/user-pool.ts index cd4e39ad03fea..22f46a92b9b8c 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/lib/http/user-pool.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/lib/http/user-pool.ts @@ -1,6 +1,6 @@ import { HttpAuthorizer, HttpAuthorizerType, HttpRouteAuthorizerBindOptions, HttpRouteAuthorizerConfig, IHttpRouteAuthorizer } from '@aws-cdk/aws-apigatewayv2'; import { IUserPool, IUserPoolClient } from '@aws-cdk/aws-cognito'; -import { Stack, Token } from '@aws-cdk/core'; +import { Stack } from '@aws-cdk/core'; /** * Properties to initialize HttpUserPoolAuthorizer. @@ -8,13 +8,9 @@ import { Stack, Token } from '@aws-cdk/core'; export interface HttpUserPoolAuthorizerProps { /** * The user pool clients that should be used to authorize requests with the user pool. + * @default - a new client will be created for the given user pool */ - readonly userPoolClients: IUserPoolClient[]; - - /** - * The associated user pool - */ - readonly userPool: IUserPool; + readonly userPoolClients?: IUserPoolClient[]; /** * The AWS region in which the user pool is present @@ -23,8 +19,8 @@ export interface HttpUserPoolAuthorizerProps { readonly userPoolRegion?: string; /** - * The name of the authorizer - * @default 'UserPoolAuthorizer' + * Friendly name of the authorizer + * @default - same value as `id` passed in the constructor */ readonly authorizerName?: string; @@ -43,21 +39,30 @@ export interface HttpUserPoolAuthorizerProps { export class HttpUserPoolAuthorizer implements IHttpRouteAuthorizer { private authorizer?: HttpAuthorizer; - constructor(private readonly props: HttpUserPoolAuthorizerProps) { + /** + * Initialize a Cognito user pool authorizer to be bound with HTTP route. + * @param id The id of the underlying construct + * @param pool The user pool to use for authorization + * @param props Properties to configure the authorizer + */ + constructor( + private readonly id: string, + private readonly pool: IUserPool, + private readonly props: HttpUserPoolAuthorizerProps = {}) { } public bind(options: HttpRouteAuthorizerBindOptions): HttpRouteAuthorizerConfig { if (!this.authorizer) { - const id = this.props.authorizerName && !Token.isUnresolved(this.props.authorizerName) ? - this.props.authorizerName : 'UserPoolAuthorizer'; const region = this.props.userPoolRegion ?? Stack.of(options.scope).region; - this.authorizer = new HttpAuthorizer(options.scope, id, { + const clients = this.props.userPoolClients ?? [this.pool.addClient('UserPoolAuthorizerClient')]; + + this.authorizer = new HttpAuthorizer(options.scope, this.id, { httpApi: options.route.httpApi, identitySource: this.props.identitySource ?? ['$request.header.Authorization'], type: HttpAuthorizerType.JWT, - authorizerName: this.props.authorizerName, - jwtAudience: this.props.userPoolClients.map((c) => c.userPoolClientId), - jwtIssuer: `https://cognito-idp.${region}.amazonaws.com/${this.props.userPool.userPoolId}`, + authorizerName: this.props.authorizerName ?? this.id, + jwtAudience: clients.map((c) => c.userPoolClientId), + jwtIssuer: `https://cognito-idp.${region}.amazonaws.com/${this.pool.userPoolId}`, }); } diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.lambda.expected.json b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.lambda.expected.json index 29ee6fe741501..921b4b1876d8f 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.lambda.expected.json +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.lambda.expected.json @@ -79,7 +79,7 @@ "RouteKey": "GET /", "AuthorizationType": "CUSTOM", "AuthorizerId": { - "Ref": "MyHttpApimysimpleauthorizer98398C16" + "Ref": "MyHttpApiLambdaAuthorizerB8A0E2A4" }, "Target": { "Fn::Join": [ @@ -94,7 +94,7 @@ } } }, - "MyHttpApimysimpleauthorizer98398C16": { + "MyHttpApiLambdaAuthorizerB8A0E2A4": { "Type": "AWS::ApiGatewayV2::Authorizer", "Properties": { "ApiId": { @@ -133,7 +133,7 @@ ] } }, - "MyHttpApiAuthorizerIntegMyHttpApimysimpleauthorizer0F14A472PermissionF37EF5C8": { + "MyHttpApiAuthorizerIntegMyHttpApiLambdaAuthorizerB89228D7Permission82260331": { "Type": "AWS::Lambda::Permission", "Properties": { "Action": "lambda:InvokeFunction", @@ -166,7 +166,7 @@ }, "/authorizers/", { - "Ref": "MyHttpApimysimpleauthorizer98398C16" + "Ref": "MyHttpApiLambdaAuthorizerB8A0E2A4" } ] ] diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.lambda.ts b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.lambda.ts index 9bc2326da21c9..5e0c32bc401d7 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.lambda.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.lambda.ts @@ -24,10 +24,9 @@ const authHandler = new lambda.Function(stack, 'auth-function', { }); -const authorizer = new HttpLambdaAuthorizer({ +const authorizer = new HttpLambdaAuthorizer('LambdaAuthorizer', authHandler, { authorizerName: 'my-simple-authorizer', identitySource: ['$request.header.X-API-Key'], - handler: authHandler, responseTypes: [HttpLambdaResponseType.SIMPLE], }); diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.user-pool.expected.json b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.user-pool.expected.json index 3e8577dfa278c..44055c596d865 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.user-pool.expected.json +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.user-pool.expected.json @@ -108,7 +108,7 @@ "JwtConfiguration": { "Audience": [ { - "Ref": "userpoolmyclientFAD947AB" + "Ref": "userpoolUserPoolAuthorizerClient6A7486E8" } ], "Issuer": { @@ -160,7 +160,7 @@ "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" }, - "userpoolmyclientFAD947AB": { + "userpoolUserPoolAuthorizerClient6A7486E8": { "Type": "AWS::Cognito::UserPoolClient", "Properties": { "UserPoolId": { diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.user-pool.ts b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.user-pool.ts index 6e9ddd8e69b5c..3c9318109dbf3 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.user-pool.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/integ.user-pool.ts @@ -21,12 +21,7 @@ const httpApi = new HttpApi(stack, 'MyHttpApi'); const userPool = new cognito.UserPool(stack, 'userpool'); -const userPoolClient = userPool.addClient('my-client'); - -const authorizer = new HttpUserPoolAuthorizer({ - userPool, - userPoolClients: [userPoolClient], -}); +const authorizer = new HttpUserPoolAuthorizer('UserPoolAuthorizer', userPool); const handler = new lambda.Function(stack, 'lambda', { runtime: lambda.Runtime.NODEJS_12_X, diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/jwt.test.ts b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/jwt.test.ts index 1d91a37438cfb..d26fff86503d1 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/jwt.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/jwt.test.ts @@ -10,9 +10,8 @@ describe('HttpJwtAuthorizer', () => { const stack = new Stack(); const api = new HttpApi(stack, 'HttpApi'); - const authorizer = new HttpJwtAuthorizer({ + const authorizer = new HttpJwtAuthorizer('BooksAuthorizer', 'https://test.us.auth0.com', { jwtAudience: ['3131231'], - jwtIssuer: 'https://test.us.auth0.com', }); // WHEN @@ -30,6 +29,7 @@ describe('HttpJwtAuthorizer', () => { Audience: ['3131231'], Issuer: 'https://test.us.auth0.com', }, + Name: 'BooksAuthorizer', }); }); @@ -38,9 +38,8 @@ describe('HttpJwtAuthorizer', () => { const stack = new Stack(); const api = new HttpApi(stack, 'HttpApi'); - const authorizer = new HttpJwtAuthorizer({ + const authorizer = new HttpJwtAuthorizer('BooksAuthorizer', 'https://test.us.auth0.com', { jwtAudience: ['3131231'], - jwtIssuer: 'https://test.us.auth0.com', }); // WHEN diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/lambda.test.ts b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/lambda.test.ts index 8ced20b3c1e1e..78d5acf7b8dfe 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/lambda.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/lambda.test.ts @@ -18,10 +18,7 @@ describe('HttpLambdaAuthorizer', () => { handler: 'index.handler', }); - const authorizer = new HttpLambdaAuthorizer({ - authorizerName: 'default-authorizer', - handler, - }); + const authorizer = new HttpLambdaAuthorizer('BooksAuthorizer', handler); // WHEN api.addRoutes({ @@ -32,7 +29,7 @@ describe('HttpLambdaAuthorizer', () => { // THEN Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Authorizer', { - Name: 'default-authorizer', + Name: 'BooksAuthorizer', AuthorizerType: 'REQUEST', AuthorizerResultTtlInSeconds: 300, AuthorizerPayloadFormatVersion: '1.0', @@ -57,10 +54,8 @@ describe('HttpLambdaAuthorizer', () => { handler: 'index.handler', }); - const authorizer = new HttpLambdaAuthorizer({ - authorizerName: 'my-simple-authorizer', + const authorizer = new HttpLambdaAuthorizer('BooksAuthorizer', handler, { responseTypes: [HttpLambdaResponseType.SIMPLE], - handler, }); // WHEN @@ -88,10 +83,8 @@ describe('HttpLambdaAuthorizer', () => { handler: 'index.handler', }); - const authorizer = new HttpLambdaAuthorizer({ - authorizerName: 'my-iam-authorizer', + const authorizer = new HttpLambdaAuthorizer('BooksAuthorizer', handler, { responseTypes: [HttpLambdaResponseType.IAM], - handler, }); // WHEN @@ -119,10 +112,8 @@ describe('HttpLambdaAuthorizer', () => { handler: 'index.handler', }); - const authorizer = new HttpLambdaAuthorizer({ - authorizerName: 'my-simple-iam-authorizer', + const authorizer = new HttpLambdaAuthorizer('BooksAuthorizer', handler, { responseTypes: [HttpLambdaResponseType.IAM, HttpLambdaResponseType.SIMPLE], - handler, }); // WHEN @@ -150,10 +141,7 @@ describe('HttpLambdaAuthorizer', () => { handler: 'index.handler', }); - const authorizer = new HttpLambdaAuthorizer({ - authorizerName: 'my-simple-authorizer', - responseTypes: [HttpLambdaResponseType.SIMPLE], - handler, + const authorizer = new HttpLambdaAuthorizer('BooksAuthorizer', handler, { resultsCacheTtl: Duration.minutes(10), }); diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/user-pool.test.ts b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/user-pool.test.ts index 21bda048b1a4d..e084bfb5dd983 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/user-pool.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/test/http/user-pool.test.ts @@ -11,11 +11,7 @@ describe('HttpUserPoolAuthorizer', () => { const stack = new Stack(); const api = new HttpApi(stack, 'HttpApi'); const userPool = new UserPool(stack, 'UserPool'); - const userPoolClient = userPool.addClient('UserPoolClient'); - const authorizer = new HttpUserPoolAuthorizer({ - userPool, - userPoolClients: [userPoolClient], - }); + const authorizer = new HttpUserPoolAuthorizer('BooksAuthorizer', userPool); // WHEN api.addRoutes({ @@ -29,7 +25,7 @@ describe('HttpUserPoolAuthorizer', () => { AuthorizerType: 'JWT', IdentitySource: ['$request.header.Authorization'], JwtConfiguration: { - Audience: [stack.resolve(userPoolClient.userPoolClientId)], + Audience: [{ Ref: 'UserPoolUserPoolAuthorizerClient680A88B6' }], Issuer: { 'Fn::Join': [ '', @@ -42,6 +38,7 @@ describe('HttpUserPoolAuthorizer', () => { ], }, }, + Name: 'BooksAuthorizer', }); }); @@ -50,11 +47,7 @@ describe('HttpUserPoolAuthorizer', () => { const stack = new Stack(); const api = new HttpApi(stack, 'HttpApi'); const userPool = new UserPool(stack, 'UserPool'); - const userPoolClient = userPool.addClient('UserPoolClient'); - const authorizer = new HttpUserPoolAuthorizer({ - userPool, - userPoolClients: [userPoolClient], - }); + const authorizer = new HttpUserPoolAuthorizer('UserPoolAuthorizer', userPool); // WHEN api.addRoutes({ @@ -79,8 +72,7 @@ describe('HttpUserPoolAuthorizer', () => { const userPool = new UserPool(stack, 'UserPool'); const userPoolClient1 = userPool.addClient('UserPoolClient1'); const userPoolClient2 = userPool.addClient('UserPoolClient2'); - const authorizer = new HttpUserPoolAuthorizer({ - userPool, + const authorizer = new HttpUserPoolAuthorizer('BooksAuthorizer', userPool, { userPoolClients: [userPoolClient1, userPoolClient2], });