Table of contents
In the Serverless Framework – Building Web App using AWS Lambda Amazon API Gateway S3 DynamoDB and Cognito – Part 1, we’ve created and deployed a simple web application using a Serverless framework. In this article, we’ll improve our results and make the application deployment declaration even more clear.
We can replace API Gateway resources with the events:
which are available on a Serverless framework.
You may find the final result, which we got at the end of the previous post at my GitHub repository. Please, use tag v1.0 as a starting point. Final result is available at tag v2.0.
Replacing API Gateway resources
First thing we need to do is to comment all resources, which has Type: AWS::ApiGateway::*
in serverless.yaml
file:

Also, you’ll need to comment WildRydesApiGatewayUrl
in the Outputs:
section, because we’re removed API Gateway declaration:

Now we can start adding the same configuration by using events:
declaration in functions:
section. Let’s publish our existing function RequestUnicorn
using API Gateway with CORS enabled:
functions:
RequestUnicorn:
handler: handler.handler
role: WildRydesLambdaRole
events:
- http:
path: ride
method: post
cors: true

I removed all not necessary comments from the file to make the file more readable.
Let’s deploy our infrastructure using the following command:
sls deploy
Now we need to implement API Gateway Authorizer. I think, we can uncomment one of the previously commented resources and modify it’s reference to the API Gateway.
WildRydesApiGatewayAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
Name: WildRydes
RestApiId:
Ref: ApiGatewayRestApi
Type: COGNITO_USER_POOLS
ProviderARNs:
- Fn::GetAtt: [WildRydesCognitoUserPool, Arn]
IdentitySource: method.request.header.Authorization

You may be interested, where I got ApiGatewayRestApi as a reference to the API Gateway, which we never declared. The reason is the Serverless framework which converts serverless.yaml
file to the CloudFormation template which we deploying each time we’re calling sls deploy
command. You may find it’s content in .serverless/cloudformation-template-update-stack.json
file inside our project structure after the first deploy.
All we need to do is to find AWS::ApiGateway::RestApi (API Gateway itself) resource declaration and take its name as a reference.

And finally, we need to add declared authorizer to our WildRydesLambdaRole
Lambda function like this:
functions:
RequestUnicorn:
handler: handler.handler
role: WildRydesLambdaRole
events:
- http:
path: ride
method: post
cors: true
authorizer:
type: COGNITO_USER_POOLS
authorizerId:
Ref: WildRydesApiGatewayAuthorizer
Let’s redeploy our stack to make sure everything’s working:
sls deploy
If you’ve already destroyed previous application, let’s upload web application static content on S3 once more again. Getting web application sources:
git clone https://github.com/awslabs/aws-serverless-workshops/
As you remember, we already described all needed Outputs:
in resources:
section of our serverless.yaml
file. So, all we need to do is to execute the following command to get it:
sls info --verbose
Now we’re ready to edit the config.js
file:
window._config = {
cognito: {
userPoolId: 'us-east-1_dADFuXCii', // e.g. us-east-2_uXboG5pAb
userPoolClientId: '5dvnlid054tvjcrv3106762bh7', // e.g. 25ddkmj4v6hfsfvruhpfi7n4hv
region: 'us-east-1', // e.g. us-east-2
},
api: {
invokeUrl: 'https://c98nutbckd.execute-api.us-east-1.amazonaws.com/dev', // e.g. https://rc7nyt4tql.execute-api.us-west-2.amazonaws.com/prod',
},
};

Now let’s upload web application content to S3 and remove it from our project sources:
aws s3 sync ./aws-serverless-workshops/WebApplication/1_StaticWebHosting/website s3://wildrydes-firstname-lastname
rm -rf ./aws-serverless-workshops
For more information about managing Amazon S3 using AWS CLI, check out our How to use AWS CLI to manage Amazon S3 article.
Redeploy the stack, if you did not do it earlier:
sls deploy
Testing
Now our application is up and running. All we need to do is to verify its functionality by opening the WildRydesBucketURL
, registering new user using /register.html
URL, verifying user manually using Cognito web interface and logging in using /ride.html
URL. The whole testing process is described in my first post and original AWS tutorial.

Final result
Let remove all commented sections and take a look under the final result:
service: wild-rides-serverless-demo # NOTE: update this with your service name
provider:
name: aws
runtime: nodejs8.10
stage: ${opt:stage, 'dev'}
functions:
RequestUnicorn:
handler: handler.handler
role: WildRydesLambdaRole
events:
- http:
path: ride
method: post
cors: true
authorizer:
type: COGNITO_USER_POOLS
authorizerId:
Ref: WildRydesApiGatewayAuthorizer
# you can add CloudFormation resource templates here
resources:
Resources:
WildRydesBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: wildrydes-andrei-maksimov
WebsiteConfiguration:
IndexDocument: index.html
WildRydesBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket:
Ref: 'WildRydesBucket'
PolicyDocument:
Statement:
- Effect: 'Allow'
Principal: '*'
Action:
- 's3:GetObject'
Resource:
Fn::Join:
- ''
- - 'arn:aws:s3:::'
- Ref: 'WildRydesBucket'
- '/*'
WildRydesCognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: WildRydes
WildRydesCognitoUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
ClientName: WildRydesWebApp
GenerateSecret: false
UserPoolId:
Ref: 'WildRydesCognitoUserPool'
WildRydesDynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: Rides
AttributeDefinitions:
- AttributeName: RideId
AttributeType: S
KeySchema:
- AttributeName: RideId
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5
WildRydesLambdaRole:
Type: AWS::IAM::Role
Properties:
RoleName: WildRydesLambda
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: DynamoDBWriteAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource:
- 'Fn::Join':
- ':'
- - 'arn:aws:logs'
- Ref: 'AWS::Region'
- Ref: 'AWS::AccountId'
- 'log-group:/aws/lambda/*:*:*'
- Effect: Allow
Action:
- dynamodb:PutItem
Resource:
'Fn::GetAtt': [WildRydesDynamoDBTable, Arn]
WildRydesApiGatewayAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
Name: WildRydes
RestApiId:
Ref: ApiGatewayRestApi
Type: COGNITO_USER_POOLS
ProviderARNs:
- Fn::GetAtt: [WildRydesCognitoUserPool, Arn]
IdentitySource: method.request.header.Authorization
Outputs:
WildRydesBucketURL:
Description: 'Wild Rydes Bucket Website URL'
Value:
'Fn::GetAtt': [WildRydesBucket, WebsiteURL]
WildRydesCognitoUserPoolId:
Description: 'Wild Rydes Cognito User Pool ID'
Value:
Ref: 'WildRydesCognitoUserPool'
WildRydesCognitoUserPoolClientId:
Description: 'Wild Rydes Cognito User Pool Client ID'
Value:
Ref: 'WildRydesCognitoUserPoolClient'
WildRydesDynamoDbARN:
Description: 'Wild Rydes DynamoDB ARN'
Value:
'Fn::GetAtt': [WildRydesDynamoDBTable, Arn]
As you can see, now we have much less code.
Resource cleanup
To cleanup everything you need to call
aws s3 rm s3://wildrydes-firstname-lastname --recursive
sls remove
Summary
We hope, you’ve found this article helpful. If you have any questions, please, feel free to ask them in the comments section. Also, you may find additional examples of API Gateway integrations using the Serverless framework in its Events documentation.
Related articles
- What is Serverless computing
- Serverless Framework – Building Web App using AWS Lambda Amazon API Gateway S3 DynamoDB and Cognito – Part 1
- Top Frameworks For Serverless Applications Development
- AWS Lambda – How to process DynamoDB streams
- Security Best Practices For Serverless Applications
How useful was this post?
Click on a star to rate it!
We are sorry that this post was not useful for you!
Let us improve this post!
Tell us how we can improve this post?
I’m a passionate Cloud Infrastructure Architect with more than 15 years of experience in IT.
Any of my posts represent my personal experience and opinion about the topic.