diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/integ-user-pool-client-explicit-props.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/integ-user-pool-client-explicit-props.template.json index 438b68c17e3c3..162fedcb222bb 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/integ-user-pool-client-explicit-props.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/integ-user-pool-client-explicit-props.template.json @@ -66,11 +66,14 @@ "ALLOW_ADMIN_USER_PASSWORD_AUTH", "ALLOW_CUSTOM_AUTH", "ALLOW_USER_SRP_AUTH", - "ALLOW_USER_AUTH", - "ALLOW_REFRESH_TOKEN_AUTH" + "ALLOW_USER_AUTH" ], "GenerateSecret": true, "PreventUserExistenceErrors": "ENABLED", + "RefreshTokenRotation": { + "Feature": "ENABLED", + "RetryGracePeriodSeconds": 45 + }, "SupportedIdentityProviders": [ "COGNITO" ], diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/tree.json index 1fb45f038441c..014d37fd713ce 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cognito/test/integ.user-pool-client-explicit-props.js.snapshot/tree.json @@ -1 +1,2 @@ -{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"integ-user-pool-client-explicit-props":{"id":"integ-user-pool-client-explicit-props","path":"integ-user-pool-client-explicit-props","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"myuserpool":{"id":"myuserpool","path":"integ-user-pool-client-explicit-props/myuserpool","constructInfo":{"fqn":"aws-cdk-lib.aws_cognito.UserPool","version":"0.0.0","metadata":[{"removalPolicy":"destroy","customAttributes":"*"}]},"children":{"Resource":{"id":"Resource","path":"integ-user-pool-client-explicit-props/myuserpool/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_cognito.CfnUserPool","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::Cognito::UserPool","aws:cdk:cloudformation:props":{"accountRecoverySetting":{"recoveryMechanisms":[{"name":"verified_phone_number","priority":1},{"name":"verified_email","priority":2}]},"adminCreateUserConfig":{"allowAdminCreateUserOnly":true},"emailVerificationMessage":"The verification code to your new account is {####}","emailVerificationSubject":"Verify your new account","schema":[{"name":"attribute_one","attributeDataType":"String"},{"name":"attribute_two","attributeDataType":"String"}],"smsVerificationMessage":"The verification code to your new account is {####}","verificationMessageTemplate":{"defaultEmailOption":"CONFIRM_WITH_CODE","emailMessage":"The verification code to your new account is {####}","emailSubject":"Verify your new account","smsMessage":"The verification code to your new account is {####}"}}}},"myuserpoolclient":{"id":"myuserpoolclient","path":"integ-user-pool-client-explicit-props/myuserpool/myuserpoolclient","constructInfo":{"fqn":"aws-cdk-lib.aws_cognito.UserPoolClient","version":"0.0.0","metadata":[{"userPool":"*","userPoolClientName":"*","authFlows":{"adminUserPassword":true,"custom":true,"userPassword":true,"userSrp":true,"user":true},"generateSecret":true,"oAuth":{"flows":{"implicitCodeGrant":true,"authorizationCodeGrant":true},"scopes":"*","callbackUrls":"*"},"preventUserExistenceErrors":true,"authSessionValidity":"*","writeAttributes":"*"}]},"children":{"Resource":{"id":"Resource","path":"integ-user-pool-client-explicit-props/myuserpool/myuserpoolclient/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_cognito.CfnUserPoolClient","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::Cognito::UserPoolClient","aws:cdk:cloudformation:props":{"allowedOAuthFlows":["implicit","code"],"allowedOAuthFlowsUserPoolClient":true,"allowedOAuthScopes":["phone","email","openid","profile","aws.cognito.signin.user.admin"],"authSessionValidity":3,"callbackUrLs":["https://redirect-here.myapp.com"],"clientName":"myuserpoolclient","explicitAuthFlows":["ALLOW_USER_PASSWORD_AUTH","ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_CUSTOM_AUTH","ALLOW_USER_SRP_AUTH","ALLOW_USER_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],"generateSecret":true,"preventUserExistenceErrors":"ENABLED","supportedIdentityProviders":["COGNITO"],"userPoolId":{"Ref":"myuserpool01998219"},"writeAttributes":["address","birthdate","custom:attribute_one","custom:attribute_two","email","family_name","gender","given_name","locale","middle_name","name","nickname","phone_number","picture","preferred_username","profile","updated_at","website","zoneinfo"]}}},"DescribeCognitoUserPoolClient":{"id":"DescribeCognitoUserPoolClient","path":"integ-user-pool-client-explicit-props/myuserpool/myuserpoolclient/DescribeCognitoUserPoolClient","constructInfo":{"fqn":"aws-cdk-lib.custom_resources.AwsCustomResource","version":"0.0.0"},"children":{"Provider":{"id":"Provider","path":"integ-user-pool-client-explicit-props/myuserpool/myuserpoolclient/DescribeCognitoUserPoolClient/Provider","constructInfo":{"fqn":"aws-cdk-lib.aws_lambda.SingletonFunction","version":"0.0.0","metadata":[{"uuid":"*","lambdaPurpose":"*","memorySize":"*","timeout":"*","role":"*","logGroup":"*","functionName":"*","vpc":"*","vpcSubnets":"*","code":"*","handler":"*","runtime":"*"},{"addMetadata":["*",true]},{"addMetadata":["*","*"]}]}},"Resource":{"id":"Resource","path":"integ-user-pool-client-explicit-props/myuserpool/myuserpoolclient/DescribeCognitoUserPoolClient/Resource","constructInfo":{"fqn":"aws-cdk-lib.CustomResource","version":"0.0.0","metadata":["*","*","*"]},"children":{"Default":{"id":"Default","path":"integ-user-pool-client-explicit-props/myuserpool/myuserpoolclient/DescribeCognitoUserPoolClient/Resource/Default","constructInfo":{"fqn":"aws-cdk-lib.CfnResource","version":"0.0.0"}}}},"CustomResourcePolicy":{"id":"CustomResourcePolicy","path":"integ-user-pool-client-explicit-props/myuserpool/myuserpoolclient/DescribeCognitoUserPoolClient/CustomResourcePolicy","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Policy","version":"0.0.0","metadata":[{"statements":"*"},{"addStatements":[{}]},{"attachToRole":["*"]},{"attachToRole":["*"]}]},"children":{"Resource":{"id":"Resource","path":"integ-user-pool-client-explicit-props/myuserpool/myuserpoolclient/DescribeCognitoUserPoolClient/CustomResourcePolicy/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnPolicy","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Policy","aws:cdk:cloudformation:props":{"policyDocument":{"Statement":[{"Action":"cognito-idp:DescribeUserPoolClient","Effect":"Allow","Resource":{"Fn::GetAtt":["myuserpool01998219","Arn"]}}],"Version":"2012-10-17"},"policyName":"myuserpoolmyuserpoolclientDescribeCognitoUserPoolClientCustomResourcePolicyF83BED40","roles":[{"Ref":"AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2"}]}}}}}}}}}}},"AWS679f53fac002430cb0da5b7982bd2287":{"id":"AWS679f53fac002430cb0da5b7982bd2287","path":"integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287","constructInfo":{"fqn":"aws-cdk-lib.aws_lambda.Function","version":"0.0.0","metadata":[{"memorySize":"*","timeout":"*","role":"*","logGroup":"*","functionName":"*","vpc":"*","vpcSubnets":"*","code":"*","handler":"*","runtime":"*"}]},"children":{"ServiceRole":{"id":"ServiceRole","path":"integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287/ServiceRole","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"assumedBy":{"principalAccount":"*","assumeRoleAction":"*"},"managedPolicies":[{"managedPolicyArn":"*"}]},{"attachInlinePolicy":["*"]}]},"children":{"ImportServiceRole":{"id":"ImportServiceRole","path":"integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287/ServiceRole/ImportServiceRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287/ServiceRole/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Role","aws:cdk:cloudformation:props":{"assumeRolePolicyDocument":{"Statement":[{"Action":"sts:AssumeRole","Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"}}],"Version":"2012-10-17"},"managedPolicyArns":[{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]]}]}}}}},"Code":{"id":"Code","path":"integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287/Code","constructInfo":{"fqn":"aws-cdk-lib.aws_s3_assets.Asset","version":"0.0.0"},"children":{"Stage":{"id":"Stage","path":"integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287/Code/Stage","constructInfo":{"fqn":"aws-cdk-lib.AssetStaging","version":"0.0.0"}},"AssetBucket":{"id":"AssetBucket","path":"integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287/Code/AssetBucket","constructInfo":{"fqn":"aws-cdk-lib.aws_s3.BucketBase","version":"0.0.0","metadata":[]}}}},"Resource":{"id":"Resource","path":"integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_lambda.CfnFunction","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::Lambda::Function","aws:cdk:cloudformation:props":{"code":{"s3Bucket":{"Fn::Sub":"cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"},"s3Key":"2b2f6e7d96d216685951807694b6e6fca88b8fd0f6ac90be6d3c75201710dd6a.zip"},"handler":"index.handler","role":{"Fn::GetAtt":["AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2","Arn"]},"runtime":"nodejs22.x","timeout":120}}}}},"Secret":{"id":"Secret","path":"integ-user-pool-client-explicit-props/Secret","constructInfo":{"fqn":"aws-cdk-lib.aws_secretsmanager.Secret","version":"0.0.0","metadata":[{"secretStringValue":"*"}]},"children":{"Resource":{"id":"Resource","path":"integ-user-pool-client-explicit-props/Secret/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_secretsmanager.CfnSecret","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::SecretsManager::Secret","aws:cdk:cloudformation:props":{"secretString":{"Fn::GetAtt":["myuserpoolmyuserpoolclientDescribeCognitoUserPoolClientEA733B32","UserPoolClient.ClientSecret"]}}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"integ-user-pool-client-explicit-props/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"integ-user-pool-client-explicit-props/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file + +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"integ-user-pool-client-explicit-props":{"id":"integ-user-pool-client-explicit-props","path":"integ-user-pool-client-explicit-props","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"myuserpool":{"id":"myuserpool","path":"integ-user-pool-client-explicit-props/myuserpool","constructInfo":{"fqn":"aws-cdk-lib.aws_cognito.UserPool","version":"0.0.0","metadata":[{"removalPolicy":"destroy","customAttributes":"*"}]},"children":{"Resource":{"id":"Resource","path":"integ-user-pool-client-explicit-props/myuserpool/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_cognito.CfnUserPool","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::Cognito::UserPool","aws:cdk:cloudformation:props":{"accountRecoverySetting":{"recoveryMechanisms":[{"name":"verified_phone_number","priority":1},{"name":"verified_email","priority":2}]},"adminCreateUserConfig":{"allowAdminCreateUserOnly":true},"emailVerificationMessage":"The verification code to your new account is {####}","emailVerificationSubject":"Verify your new account","schema":[{"name":"attribute_one","attributeDataType":"String"},{"name":"attribute_two","attributeDataType":"String"}],"smsVerificationMessage":"The verification code to your new account is {####}","verificationMessageTemplate":{"defaultEmailOption":"CONFIRM_WITH_CODE","emailMessage":"The verification code to your new account is {####}","emailSubject":"Verify your new account","smsMessage":"The verification code to your new account is {####}"}}}},"myuserpoolclient":{"id":"myuserpoolclient","path":"integ-user-pool-client-explicit-props/myuserpool/myuserpoolclient","constructInfo":{"fqn":"aws-cdk-lib.aws_cognito.UserPoolClient","version":"0.0.0","metadata":[{"userPool":"*","userPoolClientName":"*","authFlows":{"adminUserPassword":true,"custom":true,"userPassword":true,"userSrp":true,"user":true},"generateSecret":true,"oAuth":{"flows":{"implicitCodeGrant":true,"authorizationCodeGrant":true},"scopes":"*","callbackUrls":"*"},"preventUserExistenceErrors":true,"authSessionValidity":"*","writeAttributes":"*"}]},"children":{"Resource":{"id":"Resource","path":"integ-user-pool-client-explicit-props/myuserpool/myuserpoolclient/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_cognito.CfnUserPoolClient","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::Cognito::UserPoolClient","aws:cdk:cloudformation:props":{"allowedOAuthFlows":["implicit","code"],"allowedOAuthFlowsUserPoolClient":true,"allowedOAuthScopes":["phone","email","openid","profile","aws.cognito.signin.user.admin"],"authSessionValidity":3,"callbackUrLs":["https://redirect-here.myapp.com"],"clientName":"myuserpoolclient","explicitAuthFlows":["ALLOW_USER_PASSWORD_AUTH","ALLOW_ADMIN_USER_PASSWORD_AUTH","ALLOW_CUSTOM_AUTH","ALLOW_USER_SRP_AUTH","ALLOW_USER_AUTH","ALLOW_REFRESH_TOKEN_AUTH"],"generateSecret":true,"preventUserExistenceErrors":"ENABLED","supportedIdentityProviders":["COGNITO"],"userPoolId":{"Ref":"myuserpool01998219"},"writeAttributes":["address","birthdate","custom:attribute_one","custom:attribute_two","email","family_name","gender","given_name","locale","middle_name","name","nickname","phone_number","picture","preferred_username","profile","updated_at","website","zoneinfo"]}}},"DescribeCognitoUserPoolClient":{"id":"DescribeCognitoUserPoolClient","path":"integ-user-pool-client-explicit-props/myuserpool/myuserpoolclient/DescribeCognitoUserPoolClient","constructInfo":{"fqn":"aws-cdk-lib.custom_resources.AwsCustomResource","version":"0.0.0"},"children":{"Provider":{"id":"Provider","path":"integ-user-pool-client-explicit-props/myuserpool/myuserpoolclient/DescribeCognitoUserPoolClient/Provider","constructInfo":{"fqn":"aws-cdk-lib.aws_lambda.SingletonFunction","version":"0.0.0","metadata":[{"uuid":"*","lambdaPurpose":"*","memorySize":"*","timeout":"*","role":"*","logGroup":"*","functionName":"*","vpc":"*","vpcSubnets":"*","code":"*","handler":"*","runtime":"*"},{"addMetadata":["*",true]},{"addMetadata":["*","*"]}]}},"Resource":{"id":"Resource","path":"integ-user-pool-client-explicit-props/myuserpool/myuserpoolclient/DescribeCognitoUserPoolClient/Resource","constructInfo":{"fqn":"aws-cdk-lib.CustomResource","version":"0.0.0","metadata":["*","*","*"]},"children":{"Default":{"id":"Default","path":"integ-user-pool-client-explicit-props/myuserpool/myuserpoolclient/DescribeCognitoUserPoolClient/Resource/Default","constructInfo":{"fqn":"aws-cdk-lib.CfnResource","version":"0.0.0"}}}},"CustomResourcePolicy":{"id":"CustomResourcePolicy","path":"integ-user-pool-client-explicit-props/myuserpool/myuserpoolclient/DescribeCognitoUserPoolClient/CustomResourcePolicy","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Policy","version":"0.0.0","metadata":[{"statements":"*"},{"addStatements":[{}]},{"attachToRole":["*"]},{"attachToRole":["*"]}]},"children":{"Resource":{"id":"Resource","path":"integ-user-pool-client-explicit-props/myuserpool/myuserpoolclient/DescribeCognitoUserPoolClient/CustomResourcePolicy/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnPolicy","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Policy","aws:cdk:cloudformation:props":{"policyDocument":{"Statement":[{"Action":"cognito-idp:DescribeUserPoolClient","Effect":"Allow","Resource":{"Fn::GetAtt":["myuserpool01998219","Arn"]}}],"Version":"2012-10-17"},"policyName":"myuserpoolmyuserpoolclientDescribeCognitoUserPoolClientCustomResourcePolicyF83BED40","roles":[{"Ref":"AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2"}]}}}}}}}}}}},"AWS679f53fac002430cb0da5b7982bd2287":{"id":"AWS679f53fac002430cb0da5b7982bd2287","path":"integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287","constructInfo":{"fqn":"aws-cdk-lib.aws_lambda.Function","version":"0.0.0","metadata":[{"memorySize":"*","timeout":"*","role":"*","logGroup":"*","functionName":"*","vpc":"*","vpcSubnets":"*","code":"*","handler":"*","runtime":"*"}]},"children":{"ServiceRole":{"id":"ServiceRole","path":"integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287/ServiceRole","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"assumedBy":{"principalAccount":"*","assumeRoleAction":"*"},"managedPolicies":[{"managedPolicyArn":"*"}]},{"attachInlinePolicy":["*"]}]},"children":{"ImportServiceRole":{"id":"ImportServiceRole","path":"integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287/ServiceRole/ImportServiceRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287/ServiceRole/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Role","aws:cdk:cloudformation:props":{"assumeRolePolicyDocument":{"Statement":[{"Action":"sts:AssumeRole","Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"}}],"Version":"2012-10-17"},"managedPolicyArns":[{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]]}]}}}}},"Code":{"id":"Code","path":"integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287/Code","constructInfo":{"fqn":"aws-cdk-lib.aws_s3_assets.Asset","version":"0.0.0"},"children":{"Stage":{"id":"Stage","path":"integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287/Code/Stage","constructInfo":{"fqn":"aws-cdk-lib.AssetStaging","version":"0.0.0"}},"AssetBucket":{"id":"AssetBucket","path":"integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287/Code/AssetBucket","constructInfo":{"fqn":"aws-cdk-lib.aws_s3.BucketBase","version":"0.0.0","metadata":[]}}}},"Resource":{"id":"Resource","path":"integ-user-pool-client-explicit-props/AWS679f53fac002430cb0da5b7982bd2287/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_lambda.CfnFunction","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::Lambda::Function","aws:cdk:cloudformation:props":{"code":{"s3Bucket":{"Fn::Sub":"cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"},"s3Key":"2b2f6e7d96d216685951807694b6e6fca88b8fd0f6ac90be6d3c75201710dd6a.zip"},"handler":"index.handler","role":{"Fn::GetAtt":["AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2","Arn"]},"runtime":"nodejs22.x","timeout":120}}}}},"Secret":{"id":"Secret","path":"integ-user-pool-client-explicit-props/Secret","constructInfo":{"fqn":"aws-cdk-lib.aws_secretsmanager.Secret","version":"0.0.0","metadata":[{"secretStringValue":"*"}]},"children":{"Resource":{"id":"Resource","path":"integ-user-pool-client-explicit-props/Secret/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_secretsmanager.CfnSecret","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::SecretsManager::Secret","aws:cdk:cloudformation:props":{"secretString":{"Fn::GetAtt":["myuserpoolmyuserpoolclientDescribeCognitoUserPoolClientEA733B32","UserPoolClient.ClientSecret"]}}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"integ-user-pool-client-explicit-props/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"integ-user-pool-client-explicit-props/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cognito/test/integ.user-pool-client-explicit-props.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-cognito/test/integ.user-pool-client-explicit-props.ts index 79d5abe6e122a..733ff3367f2ba 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cognito/test/integ.user-pool-client-explicit-props.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cognito/test/integ.user-pool-client-explicit-props.ts @@ -43,6 +43,7 @@ const client = userpool.addClient('myuserpoolclient', { }, preventUserExistenceErrors: true, authSessionValidity: Duration.minutes(3), + refreshTokenRotationGracePeriod: Duration.seconds(45), writeAttributes: (new ClientAttributes()).withStandardAttributes( { address: true, diff --git a/packages/aws-cdk-lib/aws-cognito/README.md b/packages/aws-cdk-lib/aws-cognito/README.md index 4812cf08fad82..b0b28056c936e 100644 --- a/packages/aws-cdk-lib/aws-cognito/README.md +++ b/packages/aws-cdk-lib/aws-cognito/README.md @@ -1004,6 +1004,17 @@ const userPoolClient = new cognito.UserPoolClient(this, 'UserPoolClient', { }); ``` +[Refresh token rotation](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-refresh-token.html#using-the-refresh-token-rotation) +can be configured to enable automatic rotation of refresh tokens. By default, refresh token rotation is disabled. When the refreshTokenRotationGracePeriod is 0, the grace period is disabled and a successful request immediately invalidates the submitted refresh token. + +```ts +const pool = new cognito.UserPool(this, 'Pool'); +pool.addClient('app-client', { + // ... + refreshTokenRotationGracePeriod: Duration.seconds(40) +}); +``` + See [Adding user device and session data to API requests](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-settings-adaptive-authentication.html#user-pool-settings-adaptive-authentication-device-fingerprint) for more information. ### Resource Servers diff --git a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-client.ts b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-client.ts index 13dbb96ed44ab..3804e50ac2ab6 100644 --- a/packages/aws-cdk-lib/aws-cognito/lib/user-pool-client.ts +++ b/packages/aws-cdk-lib/aws-cognito/lib/user-pool-client.ts @@ -321,6 +321,14 @@ export interface UserPoolClientOptions { */ readonly accessTokenValidity?: Duration; + /** + * Enables refresh token rotation when set. + * Defines the grace period for the original refresh token (0-60 seconds). + * @see https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-refresh-token.html#using-the-refresh-token-rotation + * @default - undefined (refresh token rotation is disabled) + */ + readonly refreshTokenRotationGracePeriod?: Duration; + /** * The set of attributes this client will be able to read. * @see https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-attributes.html#user-pool-settings-attribute-permissions-and-scopes @@ -531,6 +539,7 @@ export class UserPoolClient extends Resource implements IUserPoolClient { }); this.configureAuthSessionValidity(resource, props); this.configureTokenValidity(resource, props); + this.configureRefreshTokenRotation(resource, props); this.userPoolClientId = resource.ref; this._userPoolClientName = props.userPoolClientName; @@ -595,8 +604,10 @@ export class UserPoolClient extends Resource implements IUserPoolClient { if (props.authFlows.userSrp) { authFlows.push('ALLOW_USER_SRP_AUTH'); } if (props.authFlows.user) { authFlows.push('ALLOW_USER_AUTH'); } - // refreshToken should always be allowed if authFlows are present - authFlows.push('ALLOW_REFRESH_TOKEN_AUTH'); + // refreshToken should only be allowed if authFlows are present and refresh token rotation is disabled + if (!props.refreshTokenRotationGracePeriod) { + authFlows.push('ALLOW_REFRESH_TOKEN_AUTH'); + } return authFlows; } @@ -674,6 +685,16 @@ export class UserPoolClient extends Resource implements IUserPoolClient { resource.accessTokenValidity = props.accessTokenValidity ? props.accessTokenValidity.toMinutes() : undefined; } + private configureRefreshTokenRotation(resource: CfnUserPoolClient, props: UserPoolClientProps) { + if (props.refreshTokenRotationGracePeriod) { + this.validateDuration('refreshTokenRotationGracePeriod', Duration.seconds(0), Duration.minutes(1), props.refreshTokenRotationGracePeriod); + resource.refreshTokenRotation = { + feature: 'ENABLED', + retryGracePeriodSeconds: props.refreshTokenRotationGracePeriod.toSeconds(), + }; + } + } + private validateDuration(name: string, min: Duration, max: Duration, value?: Duration) { if (value === undefined) { return; } if (value.toMilliseconds() < min.toMilliseconds() || value.toMilliseconds() > max.toMilliseconds()) { diff --git a/packages/aws-cdk-lib/aws-cognito/test/user-pool-client.test.ts b/packages/aws-cdk-lib/aws-cognito/test/user-pool-client.test.ts index 30cd10bc08339..9293d6ebe4ffc 100644 --- a/packages/aws-cdk-lib/aws-cognito/test/user-pool-client.test.ts +++ b/packages/aws-cdk-lib/aws-cognito/test/user-pool-client.test.ts @@ -1591,4 +1591,131 @@ describe('User Pool Client', () => { ).toThrow('Either all of `applicationId`, `externalId` and `role` must be specified or `application` must be specified.'); }); }); + + describe('refresh token rotation', () => { + test('undefined by default', () => { + const stack = new Stack(); + const pool = new UserPool(stack, 'Pool'); + + // WHEN + pool.addClient('Client', { + userPoolClientName: 'Client', + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolClient', { + ClientName: 'Client', + refreshTokenRotation: Match.absent(), + }); + }); + + test('validate grace period original refresh token', () => { + const stack = new Stack(); + const pool = new UserPool(stack, 'Pool'); + + // WHEN + pool.addClient('Client1', { + userPoolClientName: 'Client1', + refreshTokenRotationGracePeriod: Duration.seconds(5), + }); + pool.addClient('Client2', { + userPoolClientName: 'Client2', + refreshTokenRotationGracePeriod: Duration.seconds(25), + }); + pool.addClient('Client3', { + userPoolClientName: 'Client3', + refreshTokenRotationGracePeriod: Duration.seconds(50), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolClient', { + ClientName: 'Client1', + RefreshTokenRotation: { + Feature: 'ENABLED', + RetryGracePeriodSeconds: 5, + }, + }); + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolClient', { + ClientName: 'Client2', + RefreshTokenRotation: { + Feature: 'ENABLED', + RetryGracePeriodSeconds: 25, + }, + }); + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolClient', { + ClientName: 'Client3', + RefreshTokenRotation: { + Feature: 'ENABLED', + RetryGracePeriodSeconds: 50, + }, + }); + }); + + test('error when exceeding max refreshTokenRotationGracePeriod', () => { + const stack = new Stack(); + const pool = new UserPool(stack, 'Pool'); + + expect(() =>pool.addClient('Client1', { + refreshTokenRotationGracePeriod: Duration.seconds(80), + })).toThrow('refreshTokenRotationGracePeriod: Must be a duration between 0 seconds and 1 minute (inclusive); received 1 minute 20 seconds.'); + }); + + test('explicitAuthFlows refresh token excluded if refresh token rotation is enabled', () => { + // GIVEN + const stack = new Stack(); + const pool = new UserPool(stack, 'Pool'); + + // WHEN + pool.addClient('Client', { + authFlows: { + adminUserPassword: true, + custom: true, + userPassword: true, + userSrp: true, + user: true, + }, + refreshTokenRotationGracePeriod: Duration.seconds(40), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolClient', { + ExplicitAuthFlows: [ + 'ALLOW_USER_PASSWORD_AUTH', + 'ALLOW_ADMIN_USER_PASSWORD_AUTH', + 'ALLOW_CUSTOM_AUTH', + 'ALLOW_USER_SRP_AUTH', + 'ALLOW_USER_AUTH', + ], + }); + }); + + test('explicitAuthFlows refresh token included if refresh token rotation is disabled', () => { + // GIVEN + const stack = new Stack(); + const pool = new UserPool(stack, 'Pool'); + + // WHEN + pool.addClient('Client', { + authFlows: { + adminUserPassword: true, + custom: true, + userPassword: true, + userSrp: true, + user: true, + }, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::UserPoolClient', { + ExplicitAuthFlows: [ + 'ALLOW_USER_PASSWORD_AUTH', + 'ALLOW_ADMIN_USER_PASSWORD_AUTH', + 'ALLOW_CUSTOM_AUTH', + 'ALLOW_USER_SRP_AUTH', + 'ALLOW_USER_AUTH', + 'ALLOW_REFRESH_TOKEN_AUTH', + ], + }); + }); + }); });