(cognito): Race condition when creating an user pool and its identity provider in the same stack
See original GitHub issueWhen creating a Cognito User Pool and a User Pool Client which uses another Cognito user pool as its identity provider, the deployment fails. It seems like this is due to the race condition between the creation of the user pool identity provider and the user pool client.
Reproduction Steps
Deploy the following stack in a freshly setup cdk project (aws-cdk libs on v. 1.114.0):
import * as cognito from '@aws-cdk/aws-cognito';
import { OAuthScope } from '@aws-cdk/aws-cognito';
import * as cdk from '@aws-cdk/core';
export class UserPool extends cdk.Construct {
constructor(scope: cdk.Construct, id: string, props: cdk.StackProps) {
super(scope, id);
const userPool = new cognito.UserPool(this, id, {
userPoolName: 'Test-UserPool',
signInAliases: { email: true },
removalPolicy: cdk.RemovalPolicy.DESTROY
})
const userPoolDomain = new cognito.CfnUserPoolDomain(this, 'TestUserPoolDomain', {
domain: 'user-pool-chaining-test',
userPoolId: userPool.userPoolId
})
const cognitoProviderName = 'RootCognito';
let provider = new cognito.CfnUserPoolIdentityProvider(this, 'IDPProvider', {
userPoolId: userPool.userPoolId,
providerName: cognitoProviderName,
providerType: 'OIDC',
providerDetails: {
client_id: '<client-id>',
client_secret: '<client-secret>',
attributes_request_method: 'POST',
oidc_issuer: '<cognito-url>',
authorize_scopes: 'openid email profile', // 'openid-connect'
}
});
const UserPoolClient = new cognito.UserPoolClient(this, 'Test-AppClient', {
userPool: userPool,
supportedIdentityProviders: [
cognito.UserPoolClientIdentityProvider.custom(provider.providerName)
],
oAuth: {
callbackUrls: ['https://my-test-callback-url.example.com'],
flows: {
authorizationCodeGrant: true,
clientCredentials: false,
implicitCodeGrant: false
},
scopes: [
OAuthScope.OPENID,
OAuthScope.EMAIL,
OAuthScope.PHONE,
OAuthScope.PROFILE
],
}
});
}
}
What did you expect to happen?
I expect the user pool client to wait for the successful creation of the user pool identity provider before starting its own creation.
What actually happened?
The creation of the stack failed with the following error:
cdk deploy
TestCognitoChainingStack: deploying...
TestCognitoChainingStack: creating CloudFormation changeset...
13:36:01 | CREATE_FAILED | AWS::Cognito::UserPoolClient | YourServiceUserpoolTestAppClientB7160A99
The provider RootCognito does not exist for User Pool eu-central-1_MXSHIJTeZ. (Service: AWSCognitoIdentityProviderService;
Status Code: 400; Error Code: InvalidParameterException; Request ID: 74c94dc4-c955-49ce-acea-d19e16435de4; Proxy: null)
new UserPoolClient (/Users/jasper/dev/test-cognito-chaining/node_modules/@aws-cdk/aws-cognito/li2 | ROLLBACK_IN_PROGRESS | AWS::CloudFormation::Stack | TestCognitoChainingStack
b/user-pool-client.ts:206:22)
\_ new UserPool (/Users/jasper/dev/test-cognito-chaining/lib/user-pool-stack.ts:36:32)
\_ new TestCognitoChainingStack (/Users/jasper/dev/test-cognito-chaining/lib/test-cognito-chaini
ng-stack.ts:8:22)
\_ Object.<anonymous> (/Users/jasper/dev/test-cognito-chaining/bin/test-cognito-chaining.ts:7:1)
\_ Module._compile (internal/modules/cjs/loader.js:1085:14)
\_ Module.m._compile (/Users/jasper/dev/test-cognito-chaining/node_modules/ts-node/src/index.ts:
1056:23)
\_ Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
\_ Object.require.extensions.<computed> [as .ts] (/Users/jasper/dev/test-cognito-chaining/node_m
odules/ts-node/src/index.ts:1059:12)
\_ Module.load (internal/modules/cjs/loader.js:950:32)
\_ Function.Module._load (internal/modules/cjs/loader.js:790:14)
\_ Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12)
\_ main (/Users/jasper/dev/test-cognito-chaining/node_modules/ts-node/src/bin.ts:198:14)
\_ Object.<anonymous> (/Users/jasper/dev/test-cognito-chaining/node_modules/ts-node/src/bin.ts:2
88:3)
\_ Module._compile (internal/modules/cjs/loader.js:1085:14)
\_ Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
\_ Module.load (internal/modules/cjs/loader.js:950:32)
\_ Function.Module._load (internal/modules/cjs/loader.js:790:14)
\_ Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12)
\_ /usr/local/Cellar/node@14/14.17.3/lib/node_modules/npm/node_modules/libnpx/index.js:268:14
❌ TestCognitoChainingStack failed: Error: The stack named TestCognitoChainingStack failed creation, it may need to be manually deleted from the AWS console: ROLLBACK_COMPLETE
at Object.waitForStackDeploy (/usr/local/lib/node_modules/aws-cdk/lib/api/util/cloudformation.ts:305:11)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at Object.deployStack (/usr/local/lib/node_modules/aws-cdk/lib/api/deploy-stack.ts:294:26)
at CdkToolkit.deploy (/usr/local/lib/node_modules/aws-cdk/lib/cdk-toolkit.ts:184:24)
at initCommandLine (/usr/local/lib/node_modules/aws-cdk/bin/cdk.ts:213:9)
The stack named TestCognitoChainingStack failed creation, it may need to be manually deleted from the AWS console: ROLLBACK_COMPLETE
Environment
- CDK CLI Version : 1.114.0 (build 7e41b6b)
- Framework Version: 1.114.0
- Node.js Version: 14.17.3
- OS : Mac OS 11.4
- Language (Version): TypeScript 3.9.7
This is 🐛 Bug Report
Issue Analytics
- State:
- Created 2 years ago
- Comments:6 (3 by maintainers)
Top Results From Across the Web
Configuring identity providers for your user pool
The identity provider creates an app ID and an app secret for your app, and you configure those values in your Amazon Cognito...
Read more >AWS Cognito & Amplify Auth - Bad, Bugged, Baffling
The new, not verified email is already taken in the user pool, which blocks any users who might have that email from using...
Read more >User Pool allows two users with same email despite ...
I think Cognito will let two users sign up with the same email, but only one will ever be able to verify/confirm the...
Read more >AWS Cognito & Amplify Auth - Bad, Bugged, Baffling - Reddit
Now you don't have 2 accounts for the same email and can use user attributes across the different authentication providers - it's a...
Read more >@aws-cdk/aws-cognito | Yarn - Package Manager
User pools can either be configured so that user name is primary sign in form, but also allows for the other three to...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
You can solve this by adding the dependency between UserPoolClient and provider manually:
CDK can’t handle this automatically because the UserPoolClient only receives the name of the provider (
provider.providerName
) as a string. This name is not sufficient to generate the dependency between both constructs.Two solution approaches (as long there is no L2 construct for UserPoolIdentityProvider):
addDependency
workaround.cognito.UserPoolClientIdentityProvider.fromCfnUserPoolIdentityProvider(provider)
. In this case, the UserPoolClient could generate the dependency automatically because it has a reference to the identity provider.⚠️COMMENT VISIBILITY WARNING⚠️
Comments on closed issues are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so.