Create an appsync api and authenticate all request with AWS Cognito User Pools.
import { CfnOutput, Stack, StackProps } from "aws-cdk-lib";
import { Construct } from "constructs";
import * as cognito from "aws-cdk-lib/aws-cognito";
import { UserPool, UserPoolClient } from "aws-cdk-lib/aws-cognito";
import * as signer from "aws-cdk-lib/aws-signer";
import {
CfnDataSource,
CfnGraphQLApi,
CfnGraphQLSchema,
CfnResolver,
} from "aws-cdk-lib/aws-appsync";
import * as iam from "aws-cdk-lib/aws-iam";
import * as lambda from "aws-cdk-lib/aws-lambda";
import { readFileSync } from "fs";
import * as path from "path";
import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";
import { Tracing } from "aws-cdk-lib/aws-lambda";
import { ManagedPolicy, Role, ServicePrincipal } from "aws-cdk-lib/aws-iam";
export class CognitoAuthCdkStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
/**
* UserPool and UserPool Client
*/
const userPool: UserPool = new cognito.UserPool(this, "CognitoUserPool", {
selfSignUpEnabled: true,
accountRecovery: cognito.AccountRecovery.PHONE_AND_EMAIL,
userVerification: {
emailStyle: cognito.VerificationEmailStyle.CODE,
},
autoVerify: {
email: true,
},
standardAttributes: {
email: {
required: true,
mutable: true,
},
},
});
const userPoolClient: UserPoolClient = new cognito.UserPoolClient(
this,
"UserPoolClient",
{
userPool,
}
);
/**
* CloudWatch Role
*/
// give appsync permission to log to cloudwatch by assigning a role
const cloudWatchRole = new iam.Role(this, "appSyncCloudWatchLogs", {
assumedBy: new iam.ServicePrincipal("appsync.amazonaws.com"),
});
cloudWatchRole.addManagedPolicy(
iam.ManagedPolicy.fromAwsManagedPolicyName(
"service-role/AWSAppSyncPushToCloudWatchLogs"
)
);
/**
* GraphQL API
*/
const sampleAppSyncApi = new CfnGraphQLApi(this, "SampleAppsyncApi", {
name: "SampleAppSyncApi",
authenticationType: "API_KEY",
additionalAuthenticationProviders: [
{
authenticationType: "AMAZON_COGNITO_USER_POOLS",
userPoolConfig: {
userPoolId: userPool.userPoolId,
awsRegion: "us-east-2",
},
},
],
userPoolConfig: {
userPoolId: userPool.userPoolId,
defaultAction: "ALLOW",
awsRegion: "us-east-2",
},
logConfig: {
fieldLogLevel: "ALL",
cloudWatchLogsRoleArn: cloudWatchRole.roleArn,
},
xrayEnabled: true,
});
/**
* Graphql Schema
*/
const apiSchema = new CfnGraphQLSchema(this, "SampleAppsyncApiSchema", {
apiId: sampleAppSyncApi.attrApiId,
definition: readFileSync("./graphql/schema.graphql").toString(),
});
const signingProfile = new signer.SigningProfile(this, "SigningProfile", {
platform: signer.Platform.AWS_LAMBDA_SHA384_ECDSA,
});
const codeSigningConfig = new lambda.CodeSigningConfig(
this,
"CodeSigningConfig",
{
signingProfiles: [signingProfile],
}
);
const userLambda = new NodejsFunction(this, "CognitoUserHandler", {
tracing: Tracing.ACTIVE,
codeSigningConfig,
runtime: lambda.Runtime.NODEJS_16_X,
handler: "handler",
entry: path.join(__dirname, "lambda-fns", "app.ts"),
memorySize: 1024,
});
userLambda.role?.addManagedPolicy(
ManagedPolicy.fromAwsManagedPolicyName(
"service-role/AWSAppSyncPushToCloudWatchLogs"
)
);
const appsyncLambdaRole = new Role(this, "LambdaRole", {
assumedBy: new ServicePrincipal("appsync.amazonaws.com"),
});
appsyncLambdaRole.addManagedPolicy(
ManagedPolicy.fromAwsManagedPolicyName("AWSLambda_FullAccess")
);
const lambdaDataSources: CfnDataSource = new CfnDataSource(
this,
"UserLambdaDatasource",
{
apiId: sampleAppSyncApi.attrApiId,
name: "UserLambdaDatasource",
type: "AWS_LAMBDA",
lambdaConfig: {
lambdaFunctionArn: userLambda.functionArn,
},
serviceRoleArn: appsyncLambdaRole.roleArn,
}
);
const createUserAccountResolver: CfnResolver = new CfnResolver(
this,
"createUserAccountResolver",
{
apiId: sampleAppSyncApi.attrApiId,
typeName: "Mutation",
fieldName: "createUserAccount",
dataSourceName: lambdaDataSources.attrName,
}
);
createUserAccountResolver.addDependsOn(apiSchema);
/**
* Outputs
*/
new CfnOutput(this, "UserPoolId", {
value: userPool.userPoolId,
});
new CfnOutput(this, "UserPoolClientId", {
value: userPoolClient.userPoolClientId,
});
new CfnOutput(this, "GraphQLAPI ID", {
value: sampleAppSyncApi.attrApiId,
});
}
}
git clone https://github.com/aws-samples/serverless-patterns
cd serverless-patterns/appsync-cognito-lambda-cdk