in packages/constructs/L3/utility/m2m-api-l3-construct/lib/m2m-api-l3-construct.ts [193:353]
private setupCognitoM2M(apiScope: ResourceServerScope): UserPool {
const userPool = new UserPool(this, 'user-pool', {
enableSmsRole: false,
userPoolName: this.props.naming.resourceName(),
selfSignUpEnabled: false,
accountRecovery: AccountRecovery.NONE,
});
MdaaNagSuppressions.addCodeResourceSuppressions(
userPool,
[
{
id: 'AwsSolutions-COG1',
reason: 'User Pool used only for app integration, and will not contain users or passwords.',
},
{ id: 'AwsSolutions-COG2', reason: 'User Pool used only for app integration, and will not contain users.' },
],
true,
);
(userPool.node.defaultChild as CfnUserPool).userPoolAddOns = {
advancedSecurityMode: 'ENFORCED',
};
const domainName = userPool.addDomain('DomainName', {
cognitoDomain: {
domainPrefix: this.props.naming.resourceName(undefined, 64),
},
});
const resourceServer = userPool.addResourceServer('resource-server', {
userPoolResourceServerName: this.props.naming.resourceName(undefined, 64),
identifier: M2MApiL3Construct.identifier,
scopes: [apiScope],
});
const oauthScope = OAuthScope.resourceServer(resourceServer, apiScope);
Object.entries(this.props.m2mApiProps.appClients || {}).forEach(appClientEntry => {
const appClientName = appClientEntry[0];
const appClientProps = appClientEntry[1];
userPool.addClient(`oauth-client-${appClientName}`, {
userPoolClientName: this.props.naming.resourceName(appClientName, 64),
idTokenValidity: appClientProps.idTokenValidityMinutes
? Duration.minutes(appClientProps.idTokenValidityMinutes)
: undefined,
accessTokenValidity: appClientProps.accessTokenValidityMinutes
? Duration.minutes(appClientProps.accessTokenValidityMinutes)
: undefined,
refreshTokenValidity: appClientProps.refreshTokenValidityHours
? Duration.hours(appClientProps.refreshTokenValidityHours)
: undefined,
authFlows: {
userPassword: false,
userSrp: false,
custom: true,
},
oAuth: {
flows: {
authorizationCodeGrant: false,
implicitCodeGrant: false,
clientCredentials: true,
},
scopes: [oauthScope],
},
preventUserExistenceErrors: true,
generateSecret: true,
enableTokenRevocation: true,
});
});
const cognitoAuthLogFunctionRole = new MdaaLambdaRole(this, 'cognito-auth-lambda-role', {
description: 'Lambda Role for Cognito Auth Logger function',
roleName: 'cognito-auth',
naming: this.props.naming,
logGroupNames: [this.props.naming.resourceName('log-auth-event')],
createParams: false,
createOutputs: false,
});
const postAuthLogFn = new MdaaLambdaFunction(this, 'postAuthLogFn', {
runtime: Runtime.NODEJS_22_X,
handler: 'index.handler',
functionName: 'log-auth-event',
role: cognitoAuthLogFunctionRole,
naming: this.props.naming,
code: Code.fromInline(`
const handler = async function(event) {
console.log("Authentication successful");
console.log("Trigger function =", event.triggerSource);
console.log("User pool = ", event.userPoolId);
console.log("App client ID = ", event.callerContext.clientId);
console.log("User ID = ", event.userName);
return event;
};
exports.handler = handler;
`),
});
MdaaNagSuppressions.addCodeResourceSuppressions(
postAuthLogFn,
[
{ id: 'NIST.800.53.R5-LambdaDLQ', reason: 'Function only logs to stdout. DLQ is not required.' },
{
id: 'NIST.800.53.R5-LambdaInsideVPC',
reason:
'Function is logging Cognito events directly to CloudWatch via stdout and is not VPC bound by design.',
},
{
id: 'NIST.800.53.R5-LambdaConcurrency',
reason: 'Function is logging successful authentication requests. Concurrency is unbounded by design.',
},
{ id: 'HIPAA.Security-LambdaDLQ', reason: 'Function only logs to stdout. DLQ is not required.' },
{ id: 'PCI.DSS.321-LambdaDLQ', reason: 'Function only logs to stdout. DLQ is not required.' },
{
id: 'HIPAA.Security-LambdaInsideVPC',
reason:
'Function is logging Cognito events directly to CloudWatch via stdout and is not VPC bound by design.',
},
{
id: 'PCI.DSS.321-LambdaInsideVPC',
reason:
'Function is logging Cognito events directly to CloudWatch via stdout and is not VPC bound by design.',
},
{
id: 'HIPAA.Security-LambdaConcurrency',
reason: 'Function is logging successful authentication requests. Concurrency is unbounded by design.',
},
{
id: 'PCI.DSS.321-LambdaConcurrency',
reason: 'Function is logging successful authentication requests. Concurrency is unbounded by design.',
},
],
true,
);
userPool.addTrigger(UserPoolOperation.POST_AUTHENTICATION, postAuthLogFn);
new MdaaParamAndOutput(this, {
...{
resourceType: 'cognito-userpool-id',
resourceId: 'm2m-cognito-userpool-id',
name: 'm2m-userpool-id',
value: userPool.userPoolProviderName,
},
naming: this.props.naming,
});
new MdaaParamAndOutput(this, {
...{
resourceType: 'cognito-userpool-domain-name',
resourceId: 'cognito-userpool-domain-name-id',
name: 'm2m-userpool-domain-id',
value: `https://${domainName.domainName}.auth.${this.region}.amazoncognito.com`,
},
naming: this.props.naming,
});
return userPool;
}