in addons/addon-base-rest-api/packages/services/lib/authentication-providers/built-in-providers/cogito-user-pool/provisioner-service.js [134:247]
async saveCognitoUserPool(providerConfig) {
this.log.info('Creating or configuring Cognito User Pool');
const aws = await this.service('aws');
const cognitoIdentityServiceProvider = new aws.sdk.CognitoIdentityServiceProvider();
const envType = this.settings.get(settingKeys.envType);
const envName = this.settings.get(settingKeys.envName);
const solutionName = this.settings.get(settingKeys.solutionName);
const userPoolName = providerConfig.userPoolName || `${envName}-${envType}-${solutionName}-userpool`;
// Get PreSignUpLambdaArn output from CFN stack, get undefined if not present
const preSignUpLambdaArn = await this.getPreSignUpLambdaArn();
const params = {
AdminCreateUserConfig: {
AllowAdminCreateUserOnly: !this.settings.getBoolean(settingKeys.enableUserSignUps),
},
LambdaConfig:
this.settings.getBoolean(settingKeys.enableNativeUserPoolUsers) &&
this.settings.getBoolean(settingKeys.autoConfirmNativeUsers)
? {
PreSignUp: preSignUpLambdaArn,
}
: undefined,
AutoVerifiedAttributes: ['email'],
Schema: [
{
Name: 'name',
Mutable: true,
Required: true,
},
{
Name: 'family_name',
Mutable: true,
Required: true,
},
{
Name: 'middle_name',
Mutable: true,
Required: false,
},
],
};
let userPoolArn;
if (providerConfig.userPoolId) {
// If userPoolId is specified then this must be for update so make sure it points to a valid cognito user pool
try {
const poolDetails = await cognitoIdentityServiceProvider
.describeUserPool({ UserPoolId: providerConfig.userPoolId })
.promise();
userPoolArn = poolDetails.UserPool.Arn;
this.log.info('Updating Cognito User Pool as per config changes, if any');
const updateParams = {
UserPoolId: providerConfig.userPoolId,
AdminCreateUserConfig: {
AllowAdminCreateUserOnly: !this.settings.getBoolean(settingKeys.enableUserSignUps),
},
LambdaConfig: {
// We don't check for autoConfirmNativeUsers and enableNativeUserPoolUsers config setting values in the update cycle
// because preSignUp lambda is created based on the same conditions, therefore this logic can set or reset the cognito trigger
PreSignUp: preSignUpLambdaArn,
},
};
await cognitoIdentityServiceProvider.updateUserPool(updateParams).promise();
} catch (err) {
if (err.code === 'ResourceNotFoundException') {
throw this.boom.badRequest(
'Can not update Cognito User Pool. No Cognito User Pool with the given userPoolId exists.',
true,
);
}
// In case of any other error, let it propagate
throw err;
}
} else {
// userPoolId is not specified so create new user pool
params.PoolName = userPoolName;
const data = await cognitoIdentityServiceProvider.createUserPool(params).promise();
userPoolArn = data.UserPool.Arn;
providerConfig.userPoolId = data.UserPool.Id;
}
// If PreSignUpLambdaArn is not undefined, allow it to be invoked by Cognito
if (!_.isUndefined(preSignUpLambdaArn)) {
const lambda = new aws.sdk.Lambda();
const invokePermParam = {
Action: 'lambda:InvokeFunction',
FunctionName: preSignUpLambdaArn,
Principal: 'cognito-idp.amazonaws.com',
StatementId: 'CognitoLambdaInvokePermission',
SourceArn: userPoolArn,
};
try {
await lambda.addPermission(invokePermParam).promise();
} catch (err) {
if (err.code === 'ResourceConflictException') {
this.log.info('Lambda invoke permission already assigned');
} else {
// In case of any other error, let it propagate
throw this.boom.badRequest(
`Adding cognito invoke permission to lambda ${preSignUpLambdaArn} failed with code: ${err.code}`,
true,
);
}
}
}
providerConfig.userPoolName = userPoolName;
return providerConfig;
}