lib/ide-services-cognito.ts (120 lines of code) (raw):

import * as cdk from "aws-cdk-lib"; import {Construct} from "constructs"; import * as cognito from 'aws-cdk-lib/aws-cognito'; import * as cr from 'aws-cdk-lib/custom-resources'; interface IdeServicesCognitoProps extends cdk.NestedStackProps { deploymentUrl: string; } export class CognitoConfig { userPoolId: string; authBaseUrl: string; clientId: string; clientSecret: string; adminUserEmail: string; constructor( userPoolId: string, authBaseUrl: string, clientId: string, clientSecret: string, adminUserEmail: string ) { this.userPoolId = userPoolId this.authBaseUrl = authBaseUrl this.clientId = clientId this.clientSecret = clientSecret this.adminUserEmail = adminUserEmail } } export class IdeServicesCognito extends cdk.NestedStack { config: CognitoConfig constructor(scope: Construct, id: string, props: IdeServicesCognitoProps) { super(scope, id, props); const deploymentUrl = props.deploymentUrl // Get admin email from context const adminUserEmail = this.node.getContext('adminUserEmail'); // Create Cognito User Pool const userPool = new cognito.UserPool(this, 'IdeServicesUserPool', { selfSignUpEnabled: false, userVerification: { emailSubject: 'Verify your email for IDE Services', emailBody: 'Thanks for signing up to IDE Services! Your verification code is {####}', emailStyle: cognito.VerificationEmailStyle.CODE, }, autoVerify: {email: true}, standardAttributes: { email: { required: true, mutable: true, }, }, passwordPolicy: { minLength: 8, requireLowercase: true, requireUppercase: true, requireDigits: true, requireSymbols: true, }, accountRecovery: cognito.AccountRecovery.EMAIL_ONLY, removalPolicy: cdk.RemovalPolicy.DESTROY, }); const userPoolDomain = userPool.addDomain('CognitoDomain', { cognitoDomain: { domainPrefix: 'ide-services', }, }); // Create Cognito User Pool Client with CloudFront domain const userPoolClient = userPool.addClient('IdeServicesWebClient', { authFlows: { userPassword: true, userSrp: true, }, oAuth: { flows: { authorizationCodeGrant: true, }, scopes: [ cognito.OAuthScope.EMAIL, cognito.OAuthScope.OPENID, cognito.OAuthScope.PROFILE, ], callbackUrls: [ `${deploymentUrl}/api/login/authenticated`, ], logoutUrls: [ `${deploymentUrl}`, ], }, generateSecret: true }); // Use AwsCustomResource to retrieve the client secret const describeUserPoolClient = new cr.AwsCustomResource(this, 'DescribeUserPoolClient', { onCreate: { service: 'CognitoIdentityServiceProvider', action: 'describeUserPoolClient', parameters: { UserPoolId: userPool.userPoolId, ClientId: userPoolClient.userPoolClientId, }, physicalResourceId: cr.PhysicalResourceId.of(userPoolClient.userPoolClientId), }, policy: cr.AwsCustomResourcePolicy.fromSdkCalls({resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE}), }); // Create admin user new cognito.CfnUserPoolUser(this, 'AdminUser', { userPoolId: userPool.userPoolId, username: adminUserEmail, userAttributes: [ { name: 'email', value: adminUserEmail, }, { name: 'email_verified', value: 'true', }, ], }); this.config = new CognitoConfig( userPool.userPoolId, userPoolDomain.baseUrl(), userPoolClient.userPoolClientId, describeUserPoolClient.getResponseField('UserPoolClient.ClientSecret'), adminUserEmail ) } }