@aws-amplify/amplify-category-auth
Version:
amplify-cli authentication plugin
903 lines • 48.6 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AmplifyAuthCognitoStack = void 0;
const cdk = __importStar(require("aws-cdk-lib"));
const s3 = __importStar(require("aws-cdk-lib/aws-s3"));
const iam = __importStar(require("aws-cdk-lib/aws-iam"));
const cognito = __importStar(require("aws-cdk-lib/aws-cognito"));
const lambda = __importStar(require("aws-cdk-lib/aws-lambda"));
const amplify_cli_core_1 = require("@aws-amplify/amplify-cli-core");
const fs = __importStar(require("fs-extra"));
const lodash_1 = __importDefault(require("lodash"));
const constants_1 = require("../constants");
const configure_sms_1 = require("../utils/configure-sms");
const CFN_TEMPLATE_FORMAT_VERSION = '2010-09-09';
const ROOT_CFN_DESCRIPTION = 'Amplify Cognito Stack for AWS Amplify CLI';
const LambdaTriggersKeys = [
'CreateAuthChallenge',
'CustomMessage',
'DefineAuthChallenge',
'PostAuthentication',
'PostConfirmation',
'PreAuthentication',
'PreSignup',
'PreTokenGeneration',
'VerifyAuthChallengeResponse',
];
const authProvidersList = {
'graph.facebook.com': 'facebookAppId',
'accounts.google.com': 'googleClientId',
'www.amazon.com': 'amazonAppId',
'appleid.apple.com': 'appleAppId',
};
class AmplifyAuthCognitoStack extends cdk.Stack {
constructor(scope, id, props) {
super(scope, id, props);
this._cfnParameterMap = new Map();
this._cfnConditionMap = new Map();
this._cfnOutputMap = new Map();
this._cfnMappingMap = new Map();
this._cfnResourceMap = new Map();
this.generateCognitoStackResources = async (props) => {
var _a, _b, _c, _d, _e, _f;
const autoVerifiedAttributes = props.autoVerifiedAttributes
? props.autoVerifiedAttributes
.concat(props.aliasAttributes ? props.aliasAttributes : [])
.filter((attr, i, aliasAttributeArray) => ['email', 'phone_number'].includes(attr) && aliasAttributeArray.indexOf(attr) === i)
: [];
const configureSMS = (0, configure_sms_1.configureSmsOption)(props);
if (props.verificationBucketName) {
this.customMessageConfirmationBucket = new s3.CfnBucket(this, 'CustomMessageConfirmationBucket', {
bucketName: cdk.Fn.conditionIf('ShouldNotCreateEnvResources', cdk.Fn.ref('verificationBucketName'), cdk.Fn.join('-', [cdk.Fn.ref('verificationBucketName'), cdk.Fn.ref('env')])).toString(),
accessControl: s3.BucketAccessControl.PRIVATE,
corsConfiguration: {
corsRules: [
{
allowedHeaders: ['Authorization', 'Content-length'],
allowedMethods: ['GET'],
allowedOrigins: ['*'],
maxAge: 3000,
},
],
},
});
this.customMessageConfirmationBucket.applyRemovalPolicy(cdk.RemovalPolicy.RETAIN);
}
if (props.authSelections !== 'identityPoolOnly') {
if (!props.useEnabledMfas || configureSMS) {
this.snsRole = new iam.CfnRole(this, 'SNSRole', {
roleName: cdk.Fn.conditionIf('ShouldNotCreateEnvResources', `${props.resourceNameTruncated}_sns-role`, cdk.Fn.join('', [
'sns',
`${props.sharedId}`,
cdk.Fn.select(3, cdk.Fn.split('-', cdk.Fn.ref('AWS::StackName'))),
'-',
cdk.Fn.ref('env'),
])).toString(),
assumeRolePolicyDocument: {
Version: '2012-10-17',
Statement: [
{
Sid: '',
Effect: 'Allow',
Principal: {
Service: 'cognito-idp.amazonaws.com',
},
Action: ['sts:AssumeRole'],
Condition: {
StringEquals: {
'sts:ExternalId': `${props.resourceNameTruncated}_role_external_id`,
},
},
},
],
},
policies: [
{
policyName: `${props.resourceNameTruncated}-sns-policy`,
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: ['sns:Publish'],
Resource: '*',
},
],
},
},
],
});
}
this.userPool = new cognito.CfnUserPool(this, 'UserPool', {
userPoolName: cdk.Fn.conditionIf('ShouldNotCreateEnvResources', cdk.Fn.ref('userPoolName'), cdk.Fn.join('', [cdk.Fn.ref('userPoolName'), '-', cdk.Fn.ref('env')])).toString(),
policies: {
passwordPolicy: {
minimumLength: cdk.Fn.ref('passwordPolicyMinLength'),
requireLowercase: props.passwordPolicyCharacters.includes('Requires Lowercase'),
requireNumbers: props.passwordPolicyCharacters.includes('Requires Numbers'),
requireSymbols: props.passwordPolicyCharacters.includes('Requires Symbols'),
requireUppercase: props.passwordPolicyCharacters.includes('Requires Uppercase'),
},
},
});
if (props.usernameCaseSensitive !== undefined) {
this.userPool.usernameConfiguration = {
caseSensitive: props.usernameCaseSensitive,
};
}
if (props.requiredAttributes && props.requiredAttributes.length > 0) {
const schemaAttributes = [];
props.requiredAttributes.forEach((attr) => {
schemaAttributes.push({
name: attr,
required: true,
mutable: true,
});
});
this.userPool.schema = schemaAttributes;
}
if (!props.breakCircularDependency && props.triggers && props.dependsOn) {
(_a = props.dependsOn) === null || _a === void 0 ? void 0 : _a.forEach((trigger) => {
if (trigger.resourceName.includes('CreateAuthChallenge')) {
this.userPool.lambdaConfig = {
createAuthChallenge: cdk.Fn.ref(`function${props.resourceName}${'CreateAuthChallenge'}Arn`),
};
}
if (trigger.resourceName.includes('CustomMessage')) {
this.userPool.lambdaConfig = {
...this.userPool.lambdaConfig,
customMessage: cdk.Fn.ref(`function${props.resourceName}${'CustomMessage'}Arn`),
};
}
if (trigger.resourceName.includes('DefineAuthChallenge')) {
this.userPool.lambdaConfig = {
...this.userPool.lambdaConfig,
defineAuthChallenge: cdk.Fn.ref(`function${props.resourceName}${'DefineAuthChallenge'}Arn`),
};
}
if (trigger.resourceName.includes('PostAuthentication')) {
this.userPool.lambdaConfig = {
...this.userPool.lambdaConfig,
postAuthentication: cdk.Fn.ref(`function${props.resourceName}${'PostAuthentication'}Arn`),
};
}
if (trigger.resourceName.includes('PostConfirmation')) {
this.userPool.lambdaConfig = {
...this.userPool.lambdaConfig,
postConfirmation: cdk.Fn.ref(`function${props.resourceName}${'PostConfirmation'}Arn`),
};
}
if (trigger.resourceName.includes('PreAuthentication')) {
this.userPool.lambdaConfig = {
...this.userPool.lambdaConfig,
preAuthentication: cdk.Fn.ref(`function${props.resourceName}${'PreAuthentication'}Arn`),
};
}
if (trigger.resourceName.includes('PreSignup')) {
this.userPool.lambdaConfig = {
...this.userPool.lambdaConfig,
preSignUp: cdk.Fn.ref(`function${props.resourceName}${'PreSignup'}Arn`),
};
}
if (trigger.resourceName.includes('PreTokenGeneration')) {
this.userPool.lambdaConfig = {
...this.userPool.lambdaConfig,
preTokenGeneration: cdk.Fn.ref(`function${props.resourceName}${'PreTokenGeneration'}Arn`),
};
}
if (trigger.resourceName.includes('VerifyAuthChallengeResponse')) {
this.userPool.lambdaConfig = {
...this.userPool.lambdaConfig,
verifyAuthChallengeResponse: cdk.Fn.ref(`function${props.resourceName}${'VerifyAuthChallengeResponse'}Arn`),
};
}
});
}
if (autoVerifiedAttributes && autoVerifiedAttributes.length > 0) {
this.userPool.autoVerifiedAttributes = autoVerifiedAttributes;
this.userPool.userAttributeUpdateSettings = {
attributesRequireVerificationBeforeUpdate: autoVerifiedAttributes,
};
}
if (autoVerifiedAttributes.includes('email')) {
this.userPool.emailVerificationMessage = cdk.Fn.ref('emailVerificationMessage');
this.userPool.emailVerificationSubject = cdk.Fn.ref('emailVerificationSubject');
}
if (props.usernameAttributes && props.usernameAttributes[0] !== 'username') {
this.userPool.usernameAttributes = cdk.Fn.ref('usernameAttributes');
}
if (props.aliasAttributes && props.aliasAttributes.length > 0) {
this.userPool.aliasAttributes = cdk.Fn.ref('aliasAttributes');
}
this.userPool.mfaConfiguration = cdk.Fn.ref('mfaConfiguration');
if (props.useEnabledMfas && props.mfaConfiguration !== 'OFF') {
if (configureSMS) {
this.userPool.enabledMfas = ['SMS_MFA'];
}
if (!lodash_1.default.isEmpty(props.mfaTypes) && ((_b = props.mfaTypes) === null || _b === void 0 ? void 0 : _b.includes('TOTP'))) {
this.userPool.enabledMfas = [...(this.userPool.enabledMfas || []), 'SOFTWARE_TOKEN_MFA'];
}
}
if (!props.useEnabledMfas || configureSMS) {
this.userPool.smsVerificationMessage = cdk.Fn.ref('smsVerificationMessage');
this.userPool.smsAuthenticationMessage = cdk.Fn.ref('smsAuthenticationMessage');
this.userPool.smsConfiguration = {
externalId: `${props.resourceNameTruncated}_role_external_id`,
snsCallerArn: cdk.Fn.getAtt('SNSRole', 'Arn').toString(),
};
}
if (configureSMS) {
this.userPool.addDependency(this.snsRole);
}
if (!props.breakCircularDependency && props.triggers && props.dependsOn) {
props.dependsOn.forEach((trigger) => {
LambdaTriggersKeys.forEach((key) => {
if (trigger.resourceName.includes(key)) {
const resourceKey = `UserPool${key}LambdaInvokePermission`;
this.lambdaConfigPermissions[`${resourceKey}`] = new lambda.CfnPermission(this, `${resourceKey}`, {
action: 'lambda:invokeFunction',
principal: 'cognito-idp.amazonaws.com',
functionName: cdk.Fn.ref(`function${props.resourceName}${key}Name`),
sourceArn: cdk.Fn.getAtt('UserPool', 'Arn').toString(),
});
}
});
});
if (!lodash_1.default.isEmpty(props.permissions)) {
this.generateIAMPolicies(props);
}
}
this.userPoolClientWeb = new cognito.CfnUserPoolClient(this, 'UserPoolClientWeb', {
userPoolId: cdk.Fn.ref('UserPool'),
clientName: `${props.resourceNameTruncated}_app_clientWeb`,
tokenValidityUnits: {
refreshToken: 'days',
},
});
if (props.userpoolClientSetAttributes) {
this.userPoolClientWeb.readAttributes = (_c = this._cfnParameterMap.get('userpoolClientReadAttributes')) === null || _c === void 0 ? void 0 : _c.valueAsList;
this.userPoolClientWeb.writeAttributes = (_d = this._cfnParameterMap.get('userpoolClientWriteAttributes')) === null || _d === void 0 ? void 0 : _d.valueAsList;
}
this.userPoolClientWeb.refreshTokenValidity = cdk.Fn.ref('userpoolClientRefreshTokenValidity');
this.userPoolClientWeb.addDependency(this.userPool);
this.userPoolClient = new cognito.CfnUserPoolClient(this, 'UserPoolClient', {
userPoolId: cdk.Fn.ref('UserPool'),
clientName: `${props.resourceNameTruncated}_app_client`,
tokenValidityUnits: {
refreshToken: 'days',
},
});
if (props.userpoolClientSetAttributes) {
this.userPoolClient.readAttributes = (_e = this._cfnParameterMap.get('userpoolClientReadAttributes')) === null || _e === void 0 ? void 0 : _e.valueAsList;
this.userPoolClient.writeAttributes = (_f = this._cfnParameterMap.get('userpoolClientWriteAttributes')) === null || _f === void 0 ? void 0 : _f.valueAsList;
}
this.userPoolClient.refreshTokenValidity = cdk.Fn.ref('userpoolClientRefreshTokenValidity');
this.userPoolClient.generateSecret = cdk.Fn.ref('userpoolClientGenerateSecret');
this.userPoolClient.addDependency(this.userPool);
this.createBaseLambdaRole(props);
if (props.oAuthMetadata) {
this.updateUserPoolClientWithOAuthSettings(props);
}
if (props.hostedUIDomainName) {
this.createHostedUICustomResource();
}
if (props.hostedUIProviderMeta) {
this.createHostedUIProviderCustomResource();
}
if (!props.useEnabledMfas && props.mfaConfiguration !== 'OFF') {
this.createMFACustomResource(props);
}
}
if (props.authSelections === 'identityPoolAndUserPool' || props.authSelections === 'identityPoolOnly') {
if (props.audiences && props.audiences.length > 0) {
this.createOpenIdLambdaCustomResource(props);
}
this.identityPool = new cognito.CfnIdentityPool(this, 'IdentityPool', {
identityPoolName: cdk.Fn.conditionIf('ShouldNotCreateEnvResources', props.identityPoolName, cdk.Fn.join('', [`${props.identityPoolName}`, '__', cdk.Fn.ref('env')])).toString(),
allowUnauthenticatedIdentities: cdk.Fn.ref('allowUnauthenticatedIdentities'),
});
if (props.authSelections !== 'identityPoolOnly') {
this.identityPool.cognitoIdentityProviders = [
{
clientId: cdk.Fn.ref('UserPoolClient'),
providerName: cdk.Fn.sub('cognito-idp.${region}.amazonaws.com/${client}', {
region: cdk.Fn.ref('AWS::Region'),
client: cdk.Fn.ref('UserPool'),
}),
},
{
clientId: cdk.Fn.ref('UserPoolClientWeb'),
providerName: cdk.Fn.sub('cognito-idp.${region}.amazonaws.com/${client}', {
region: cdk.Fn.ref('AWS::Region'),
client: cdk.Fn.ref('UserPool'),
}),
},
];
}
if (props.authProviders &&
!lodash_1.default.isEmpty(props.authProviders) &&
!(Object.keys(props.authProviders).length === 1 && props.authProviders[0] === 'accounts.google.com' && props.audiences)) {
this.identityPool.supportedLoginProviders = cdk.Lazy.any({
produce: () => {
var _a;
const supportedProvider = {};
(_a = props.authProviders) === null || _a === void 0 ? void 0 : _a.forEach((provider) => {
if (Object.keys(authProvidersList).includes(provider)) {
supportedProvider[provider] = cdk.Fn.ref(authProvidersList[provider]);
}
});
return supportedProvider;
},
});
}
if (props.audiences && props.audiences.length > 0) {
this.identityPool.openIdConnectProviderArns = [cdk.Fn.getAtt('OpenIdLambdaInputs', 'providerArn').toString()];
this.identityPool.node.addDependency(this.openIdLambdaInputs.node.defaultChild);
}
let identityPoolRoleMapParams = {
identityPoolId: cdk.Fn.ref('IdentityPool'),
roles: {
unauthenticated: cdk.Fn.ref('unauthRoleArn'),
authenticated: cdk.Fn.ref('authRoleArn'),
},
};
const addRoleMappingAttachments = props.userPoolGroups || (props.userPoolGroupList || []).length > 0;
if (addRoleMappingAttachments) {
const roleMappings = {
roleMappings: {
UserPoolClientRoleMapping: {
identityProvider: cdk.Fn.sub('cognito-idp.${region}.amazonaws.com/${userPool}:${client}', {
region: cdk.Fn.ref('AWS::Region'),
userPool: cdk.Fn.ref('UserPool'),
client: cdk.Fn.ref('UserPoolClient'),
}),
ambiguousRoleResolution: 'AuthenticatedRole',
type: 'Token',
},
UserPoolWebClientRoleMapping: {
identityProvider: cdk.Fn.sub('cognito-idp.${region}.amazonaws.com/${userPool}:${webClient}', {
region: cdk.Fn.ref('AWS::Region'),
userPool: cdk.Fn.ref('UserPool'),
webClient: cdk.Fn.ref('UserPoolClientWeb'),
}),
ambiguousRoleResolution: 'AuthenticatedRole',
type: 'Token',
},
},
};
identityPoolRoleMapParams = {
...identityPoolRoleMapParams,
...roleMappings,
};
}
this.identityPoolRoleMap = new cognito.CfnIdentityPoolRoleAttachment(this, 'IdentityPoolRoleMap', identityPoolRoleMapParams);
this.identityPoolRoleMap.addDependency(this.identityPool);
if (addRoleMappingAttachments) {
if (this.userPoolClient) {
this.identityPoolRoleMap.addDependency(this.userPoolClient);
}
if (this.userPoolClientWeb) {
this.identityPoolRoleMap.addDependency(this.userPoolClientWeb);
}
}
}
};
this.renderCloudFormationTemplate = () => amplify_cli_core_1.JSONUtilities.stringify(this._toCloudFormation());
this.updateUserPoolClientWithOAuthSettings = (props) => {
const oAuthMetaData = amplify_cli_core_1.JSONUtilities.parse(props.oAuthMetadata);
let hostedUIProviderMeta;
let supportedIdentityProviders = [];
if (!lodash_1.default.isEmpty(props.hostedUIProviderMeta)) {
hostedUIProviderMeta = amplify_cli_core_1.JSONUtilities.parse(props.hostedUIProviderMeta);
supportedIdentityProviders = hostedUIProviderMeta.map((provider) => provider.ProviderName);
}
supportedIdentityProviders.push('COGNITO');
if (this.userPoolClient) {
this.userPoolClient.allowedOAuthFlowsUserPoolClient = true;
this.userPoolClient.allowedOAuthScopes = oAuthMetaData === null || oAuthMetaData === void 0 ? void 0 : oAuthMetaData.AllowedOAuthScopes;
this.userPoolClient.allowedOAuthFlows = oAuthMetaData === null || oAuthMetaData === void 0 ? void 0 : oAuthMetaData.AllowedOAuthFlows;
this.userPoolClient.callbackUrLs = oAuthMetaData === null || oAuthMetaData === void 0 ? void 0 : oAuthMetaData.CallbackURLs;
this.userPoolClient.logoutUrLs = oAuthMetaData === null || oAuthMetaData === void 0 ? void 0 : oAuthMetaData.LogoutURLs;
this.userPoolClient.supportedIdentityProviders = supportedIdentityProviders;
}
if (this.userPoolClientWeb) {
this.userPoolClientWeb.allowedOAuthFlowsUserPoolClient = true;
this.userPoolClientWeb.allowedOAuthScopes = oAuthMetaData === null || oAuthMetaData === void 0 ? void 0 : oAuthMetaData.AllowedOAuthScopes;
this.userPoolClientWeb.allowedOAuthFlows = oAuthMetaData === null || oAuthMetaData === void 0 ? void 0 : oAuthMetaData.AllowedOAuthFlows;
this.userPoolClientWeb.callbackUrLs = oAuthMetaData === null || oAuthMetaData === void 0 ? void 0 : oAuthMetaData.CallbackURLs;
this.userPoolClientWeb.logoutUrLs = oAuthMetaData === null || oAuthMetaData === void 0 ? void 0 : oAuthMetaData.LogoutURLs;
this.userPoolClientWeb.supportedIdentityProviders = supportedIdentityProviders;
}
};
this.generateIAMPolicies = (props) => {
var _a;
let resource;
(_a = props.permissions) === null || _a === void 0 ? void 0 : _a.forEach((permission) => {
if (permission.resource.paramType === 'string') {
resource = permission.resource.keys;
}
if (permission.resource.paramType === '!GetAtt') {
resource = cdk.Fn.getAtt(permission.resource.keys[0], permission.resource.keys[1]).toString();
}
if (permission.resource.paramType === '!Ref') {
resource = cdk.Fn.ref(permission.resource.keys);
}
const resourceKey = `${props.resourceName}${permission.trigger}${permission.policyName}`;
this.lambdaTriggerPermissions[resourceKey] = new iam.CfnPolicy(this, resourceKey, {
policyName: resourceKey,
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: permission.effect,
Action: permission.actions,
Resource: resource,
},
],
},
roles: [cdk.Fn.join('', [`${props.resourceName}${permission.trigger}`, '-', cdk.Fn.ref('env')])],
});
});
};
this._scope = scope;
this.templateOptions.templateFormatVersion = CFN_TEMPLATE_FORMAT_VERSION;
this.templateOptions.description = ROOT_CFN_DESCRIPTION;
this.lambdaConfigPermissions = {};
this.lambdaTriggerPermissions = {};
}
addCfnResource(props, logicalId) {
if (!this._cfnResourceMap.has(logicalId)) {
this._cfnResourceMap.set(logicalId, new cdk.CfnResource(this, logicalId, props));
}
else {
throw new Error(`Cfn Resource with LogicalId ${logicalId} already exists`);
}
}
getCfnOutput(logicalId) {
if (this._cfnOutputMap.has(logicalId)) {
return this._cfnOutputMap.get(logicalId);
}
throw new Error(`Cfn Output with LogicalId ${logicalId} doesn't exist`);
}
getCfnMapping(logicalId) {
if (this._cfnMappingMap.has(logicalId)) {
return this._cfnMappingMap.get(logicalId);
}
throw new Error(`Cfn Mapping with LogicalId ${logicalId} doesn't exist`);
}
addCfnOutput(props, logicalId) {
if (!this._cfnOutputMap.has(logicalId)) {
this._cfnOutputMap.set(logicalId, new cdk.CfnOutput(this, logicalId, props));
}
else {
throw new Error(`Cfn Parameter with LogicalId ${logicalId} already exists`);
}
}
addCfnMapping(props, logicalId) {
if (!this._cfnMappingMap.has(logicalId)) {
this._cfnMappingMap.set(logicalId, new cdk.CfnMapping(this, logicalId, props));
}
else {
throw new Error(`Cfn Parameter with LogicalId ${logicalId} already exists`);
}
}
addCfnCondition(props, logicalId) {
if (!this._cfnConditionMap.has(logicalId)) {
this._cfnConditionMap.set(logicalId, new cdk.CfnCondition(this, logicalId, props));
}
else {
throw new Error(`Cfn Parameter with LogicalId ${logicalId} already exists`);
}
}
addCfnParameter(props, logicalId) {
if (!this._cfnParameterMap.has(logicalId)) {
this._cfnParameterMap.set(logicalId, new cdk.CfnParameter(this, logicalId, props));
}
else {
throw new Error(`Cfn Parameter with LogicalId ${logicalId} already exists`);
}
}
getCfnParameter(logicalId) {
if (this._cfnParameterMap.has(logicalId)) {
return this._cfnParameterMap.get(logicalId);
}
throw new Error(`Cfn Parameter with LogicalId ${logicalId} doesn't exist`);
}
getCfnCondition(logicalId) {
if (this._cfnConditionMap.has(logicalId)) {
return this._cfnConditionMap.get(logicalId);
}
throw new Error(`Cfn Condition with LogicalId ${logicalId} doesn't exist`);
}
createBaseLambdaRole(props) {
this.userPoolClientRole = new iam.CfnRole(this, 'UserPoolClientRole', {
roleName: cdk.Fn.conditionIf('ShouldNotCreateEnvResources', cdk.Fn.ref('userpoolClientLambdaRole'), cdk.Fn.join('', [
'upClientLambdaRole',
`${props.sharedId}`,
cdk.Fn.select(3, cdk.Fn.split('-', cdk.Fn.ref('AWS::StackName'))),
'-',
cdk.Fn.ref('env'),
])).toString(),
assumeRolePolicyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Principal: {
Service: 'lambda.amazonaws.com',
},
Action: 'sts:AssumeRole',
},
],
},
});
}
createHostedUICustomResource() {
this.hostedUICustomResource = new lambda.CfnFunction(this, 'HostedUICustomResource', {
code: {
zipFile: fs.readFileSync(constants_1.hostedUILambdaFilePath, 'utf-8'),
},
handler: 'index.handler',
role: cdk.Fn.getAtt('UserPoolClientRole', 'Arn').toString(),
runtime: 'nodejs22.x',
timeout: 300,
});
if (this.userPoolClientRole) {
this.hostedUICustomResource.addDependency(this.userPoolClientRole);
}
this.hostedUICustomResourcePolicy = new iam.CfnPolicy(this, 'HostedUICustomResourcePolicy', {
policyName: cdk.Fn.join('-', [cdk.Fn.ref('UserPool'), cdk.Fn.ref('hostedUI')]),
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: ['cognito-idp:CreateUserPoolDomain', 'cognito-idp:DescribeUserPool', 'cognito-idp:DeleteUserPoolDomain'],
Resource: cdk.Fn.getAtt('UserPool', 'Arn'),
},
{
Effect: 'Allow',
Action: ['cognito-idp:DescribeUserPoolDomain'],
Resource: '*',
},
],
},
roles: [cdk.Fn.ref('UserPoolClientRole')],
});
this.hostedUICustomResourcePolicy.addDependency(this.hostedUICustomResource);
this.hostedUICustomResourceLogPolicy = new iam.CfnPolicy(this, 'HostedUICustomResourceLogPolicy', {
policyName: cdk.Fn.join('-', [cdk.Fn.ref('UserPool'), 'hostedUILogPolicy']),
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: ['logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents'],
Resource: cdk.Fn.sub('arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:*', {
region: cdk.Fn.ref('AWS::Region'),
account: cdk.Fn.ref('AWS::AccountId'),
lambda: cdk.Fn.ref('HostedUICustomResource'),
}),
},
],
},
roles: [cdk.Fn.ref('UserPoolClientRole')],
});
this.hostedUICustomResourceLogPolicy.addDependency(this.hostedUICustomResourcePolicy);
this.hostedUICustomResourceInputs = new cdk.CustomResource(this, 'HostedUICustomResourceInputs', {
serviceToken: this.hostedUICustomResource.attrArn,
resourceType: 'Custom::LambdaCallout',
properties: {
hostedUIDomainName: cdk.Fn.conditionIf('ShouldNotCreateEnvResources', cdk.Fn.ref('hostedUIDomainName'), cdk.Fn.join('-', [cdk.Fn.ref('hostedUIDomainName'), cdk.Fn.ref('env')])),
userPoolId: cdk.Fn.ref('UserPool'),
},
});
this.hostedUICustomResourceInputs.node.addDependency(this.hostedUICustomResourceLogPolicy);
}
createHostedUIProviderCustomResource() {
var _a, _b;
this.hostedUIProvidersCustomResource = new lambda.CfnFunction(this, 'HostedUIProvidersCustomResource', {
code: {
zipFile: fs.readFileSync(constants_1.hostedUIProviderLambdaFilePath, 'utf-8'),
},
handler: 'index.handler',
role: cdk.Fn.getAtt('UserPoolClientRole', 'Arn').toString(),
runtime: 'nodejs22.x',
timeout: 300,
});
if (this.userPoolClientRole) {
this.hostedUIProvidersCustomResource.addDependency(this.userPoolClientRole);
}
this.hostedUIProvidersCustomResourcePolicy = new iam.CfnPolicy(this, 'HostedUIProvidersCustomResourcePolicy', {
policyName: cdk.Fn.join('-', [cdk.Fn.ref('UserPool'), 'hostedUIProvider']),
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: [
'cognito-idp:CreateIdentityProvider',
'cognito-idp:UpdateIdentityProvider',
'cognito-idp:ListIdentityProviders',
'cognito-idp:DeleteIdentityProvider',
],
Resource: cdk.Fn.getAtt('UserPool', 'Arn'),
},
{
Effect: 'Allow',
Action: ['cognito-idp:DescribeUserPoolDomain'],
Resource: '*',
},
],
},
roles: [cdk.Fn.ref('UserPoolClientRole')],
});
this.hostedUIProvidersCustomResourcePolicy.addDependency(this.hostedUIProvidersCustomResource);
this.hostedUIProvidersCustomResourceLogPolicy = new iam.CfnPolicy(this, 'HostedUIProvidersCustomResourceLogPolicy', {
policyName: cdk.Fn.join('-', [cdk.Fn.ref('UserPool'), 'hostedUIProviderLogPolicy']),
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: ['logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents'],
Resource: cdk.Fn.sub('arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:*', {
region: cdk.Fn.ref('AWS::Region'),
account: cdk.Fn.ref('AWS::AccountId'),
lambda: cdk.Fn.ref('HostedUIProvidersCustomResource'),
}),
},
],
},
roles: [cdk.Fn.ref('UserPoolClientRole')],
});
this.hostedUIProvidersCustomResourceLogPolicy.addDependency(this.hostedUIProvidersCustomResourcePolicy);
this.hostedUIProvidersCustomResourceInputs = new cdk.CustomResource(this, 'HostedUIProvidersCustomResourceInputs', {
serviceToken: this.hostedUIProvidersCustomResource.attrArn,
resourceType: 'Custom::LambdaCallout',
properties: {
hostedUIProviderMeta: cdk.Fn.ref('hostedUIProviderMeta'),
hostedUIProviderCreds: cdk.Fn.ref('hostedUIProviderCreds'),
userPoolId: cdk.Fn.ref('UserPool'),
},
});
this.hostedUIProvidersCustomResourceInputs.node.addDependency(this.hostedUIProvidersCustomResourceLogPolicy);
(_a = this.userPoolClient) === null || _a === void 0 ? void 0 : _a.node.addDependency(this.hostedUIProvidersCustomResourceInputs);
(_b = this.userPoolClientWeb) === null || _b === void 0 ? void 0 : _b.node.addDependency(this.hostedUIProvidersCustomResourceInputs);
}
createMFACustomResource(props) {
this.mfaLambdaRole = new iam.CfnRole(this, 'MFALambdaRole', {
roleName: cdk.Fn.conditionIf('ShouldNotCreateEnvResources', `${props.resourceNameTruncated}_totp_lambda_role`, cdk.Fn.join('', [`${props.resourceNameTruncated}_totp_lambda_role`, '-', cdk.Fn.ref('env')])).toString(),
assumeRolePolicyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Principal: {
Service: 'lambda.amazonaws.com',
},
Action: 'sts:AssumeRole',
},
],
},
policies: [
{
policyName: `${props.resourceNameTruncated}_totp_pass_role_policy`,
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: ['iam:PassRole'],
Resource: cdk.Fn.conditionIf('ShouldNotCreateEnvResources', `arn:aws:iam:::role/${props.resourceNameTruncated}_totp_lambda_role`, cdk.Fn.join('', [`arn:aws:iam:::role/${props.resourceNameTruncated}__totp_lambda_role`, '-', cdk.Fn.ref('env')])),
},
],
},
},
{
policyName: `${props.resourceNameTruncated}_sns_pass_role_policy`,
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: ['iam:PassRole'],
Resource: cdk.Fn.getAtt('SNSRole', 'Arn'),
},
],
},
},
],
});
this.mfaLambdaRole.addDependency(this.snsRole);
this.mfaLambda = new lambda.CfnFunction(this, 'MFALambda', {
code: {
zipFile: fs.readFileSync(constants_1.mfaLambdaFilePath, 'utf-8'),
},
handler: 'index.handler',
role: cdk.Fn.getAtt('MFALambdaRole', 'Arn').toString(),
runtime: 'nodejs22.x',
timeout: 300,
});
this.mfaLambda.addDependency(this.mfaLambdaRole);
this.mfaLambdaPolicy = new iam.CfnPolicy(this, 'MFALambdaPolicy', {
policyName: `${props.resourceNameTruncated}_totp_lambda_iam_policy`,
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: ['cognito-idp:SetUserPoolMfaConfig'],
Resource: cdk.Fn.getAtt('UserPool', 'Arn'),
},
],
},
roles: [
cdk.Fn.conditionIf('ShouldNotCreateEnvResources', `${props.resourceNameTruncated}_totp_lambda_role`, cdk.Fn.join('', [`${props.resourceNameTruncated}_totp_lambda_role`, '-', cdk.Fn.ref('env')])).toString(),
],
});
this.mfaLambdaPolicy.addDependency(this.mfaLambda);
this.mfaLogPolicy = new iam.CfnPolicy(this, 'MFALogPolicy', {
policyName: `${props.resourceNameTruncated}_totp_lambda_log_policy`,
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: ['logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents'],
Resource: cdk.Fn.sub('arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:*', {
region: cdk.Fn.ref('AWS::Region'),
account: cdk.Fn.ref('AWS::AccountId'),
lambda: cdk.Fn.ref('MFALambda'),
}),
},
],
},
roles: [
cdk.Fn.conditionIf('ShouldNotCreateEnvResources', `${props.resourceNameTruncated}_totp_lambda_role`, cdk.Fn.join('', [`${props.resourceNameTruncated}_totp_lambda_role`, '-', cdk.Fn.ref('env')])).toString(),
],
});
this.mfaLogPolicy.addDependency(this.mfaLambdaPolicy);
this.mfaLambdaInputs = new cdk.CustomResource(this, 'MFALambdaInputs', {
serviceToken: this.mfaLambda.attrArn,
resourceType: 'Custom::LambdaCallout',
properties: {
mfaConfiguration: cdk.Fn.ref('mfaConfiguration'),
totpEnabled: props.mfaTypes.includes('TOTP'),
smsConfigCaller: cdk.Fn.getAtt('SNSRole', 'Arn'),
smsAuthenticationMessage: cdk.Fn.ref('smsAuthenticationMessage'),
smsConfigExternalId: `${props.resourceNameTruncated}_role_external_id`,
userPoolId: cdk.Fn.ref('UserPool'),
},
});
this.mfaLambdaInputs.node.addDependency(this.mfaLogPolicy);
}
createOpenIdLambdaCustomResource(props) {
var _a;
this.openIdLambdaRole = new iam.CfnRole(this, 'OpenIdLambdaRole', {
roleName: cdk.Fn.conditionIf('ShouldNotCreateEnvResources', `${props.resourceNameTruncated}_openid_lambda_role`, cdk.Fn.join('', [`${props.resourceNameTruncated}_openid_lambda_role`, '-', cdk.Fn.ref('env')])).toString(),
assumeRolePolicyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Principal: {
Service: 'lambda.amazonaws.com',
},
Action: 'sts:AssumeRole',
},
],
},
policies: [
{
policyName: `${props.resourceNameTruncated}_openid_pass_role_policy`,
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: ['iam:PassRole'],
Resource: cdk.Fn.conditionIf('ShouldNotCreateEnvResources', `arn:aws:iam:::role/${props.resourceNameTruncated}_openid_pass_role_policy`, cdk.Fn.join('', [`arn:aws:iam:::role/${props.resourceNameTruncated}_openid_pass_role_policy`, '-', cdk.Fn.ref('env')])),
},
],
},
},
],
});
this.openIdLambda = new lambda.CfnFunction(this, 'OpenIdLambda', {
code: {
zipFile: fs.readFileSync(constants_1.openIdLambdaFilePath, 'utf-8'),
},
handler: 'index.handler',
role: cdk.Fn.getAtt('OpenIdLambdaRole', 'Arn').toString(),
runtime: 'nodejs22.x',
timeout: 300,
});
this.openIdLambda.addDependency(this.openIdLambdaRole);
this.openIdLambdaIAMPolicy = new iam.CfnPolicy(this, 'OpenIdLambdaIAMPolicy', {
policyName: `${props.resourceNameTruncated}_openid_lambda_iam_policy`,
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: ['iam:CreateOpenIDConnectProvider', 'iam:GetOpenIDConnectProvider', 'iam:AddClientIDToOpenIDConnectProvider'],
Resource: cdk.Fn.sub('arn:aws:iam::${account}:oidc-provider/accounts.google.com', {
account: cdk.Fn.ref('AWS::AccountId'),
}),
},
{
Effect: 'Allow',
Action: ['iam:ListOpenIDConnectProviders'],
Resource: cdk.Fn.sub('arn:aws:iam::${account}:oidc-provider/${selector}', {
account: cdk.Fn.ref('AWS::AccountId'),
selector: '*',
}),
},
],
},
roles: [
cdk.Fn.conditionIf('ShouldNotCreateEnvResources', `${props.resourceNameTruncated}_openid_lambda_role`, cdk.Fn.join('', [`${props.resourceNameTruncated}_openid_lambda_role`, '-', cdk.Fn.ref('env')])).toString(),
],
});
this.openIdLambdaIAMPolicy.addDependency(this.openIdLambda);
this.openIdLogPolicy = new iam.CfnPolicy(this, 'OpenIdLogPolicy', {
policyName: `${props.resourceNameTruncated}_openid_lambda_log_policy`,
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: ['logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents'],
Resource: cdk.Fn.sub('arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:*', {
region: cdk.Fn.ref('AWS::Region'),
account: cdk.Fn.ref('AWS::AccountId'),
lambda: cdk.Fn.ref('OpenIdLambda'),
}),
},
],
},
roles: [
cdk.Fn.conditionIf('ShouldNotCreateEnvResources', `${props.resourceNameTruncated}_openid_lambda_role`, cdk.Fn.join('', [`${props.resourceNameTruncated}_openid_lambda_role`, '-', cdk.Fn.ref('env')])).toString(),
],
});
this.openIdLogPolicy.addDependency(this.openIdLambdaIAMPolicy);
this.openIdLambdaInputs = new cdk.CustomResource(this, 'OpenIdLambdaInputs', {
serviceToken: this.openIdLambda.attrArn,
resourceType: 'Custom::LambdaCallout',
properties: {
clientIdList: (_a = props.audiences) === null || _a === void 0 ? void 0 : _a.join(),
url: 'https://accounts.google.com',
},
});
this.openIdLambdaInputs.node.addDependency(this.openIdLogPolicy);
}
}
exports.AmplifyAuthCognitoStack = AmplifyAuthCognitoStack;
//# sourceMappingURL=auth-cognito-stack-builder.js.map