How to add Amazon Cognito Auth to a Web App (part 4)

Looking at the NodeJS logic that is run in lambda functions to power the Back End of Amazon Cognito Authentication.

Table of Contents


In myย last post, I explained how Amazon Cognito is integrated into the Front End, to allow content to become visible to users that have gone through the Auth process as shown in the below demo ๐Ÿ‘‡

In this post, I’ll explain how this same process can be implemented in the Back End.

If you look at the right side of the above gif, you will see an open console log. Please note the ‘Hello World!! ๐Ÿ˜€‘ message that appears in the logs once the user has successfully signed in.

This message is returned to users, that have logged into the Front End and then gone through the Auth process on the Back End.

Implementing Cognito Auth on the Back End

I have aย Wrapper.js templateย that you can use to spin up an implementation of Cognito, here are some highlight files from that template:


					service: ${file(./../../../serverless.env.json):service_name}-${file(./../../../serverless.env.json):stage}

  environment: ${file(./../../../serverless.env.json)}
  name: aws
  region: ${file(./../../../serverless.env.json):region}
  runtime: nodejs12.x
  stage: ${file(./../../../serverless.env.json):stage}
  apiGateway: # Optional API Gateway global config
    restApiId: ${file(./../../../serverless.env.json):api_gateway_rest_api_id} # REST API resource ID. Default is generated by the framework
    restApiRootResourceId: ${file(./../../../serverless.env.json):api_gateway_root_resource_id} # Root resource ID, represent as / path
        - Effect: Allow
            - dynamodb:Query
            - dynamodb:Scan
            - dynamodb:GetItem
            - dynamodb:PutItem
            - dynamodb:UpdateItem
            - dynamodb:DeleteItem
          Resource: "*"
        - Effect: Allow
            - "execute-api:ManageConnections"
            - "arn:aws:execute-api:*:*:**/@connections/*"

    id : ${file(./../../../serverless.env.json):cognito_authorizer}
    host: ''   

Serverless Framework in WrapperJS is organised into HTTP and Websocket services, each service has its own yaml configuration.

Variables that are exported from Terraform (the cognito details) are passed to the above file, which the individual services can then reference.

These variables are:

  • restApiId: the ID of the API Gateway that Serverless Framework should deploy lambda end points to
  • ย restApiIdRootResourceId: the root path of that API Gateway, that all lambda endpoints will be added to
  • apiAuthorizer: an API Authorizer that was created by Terraform from the ARN of the Cognito User Pool


					service: ${file(./../../../serverless.common.yml):service}-${self:custom.service}
useDotenv: true

provider: ${self:custom.common.provider}

  - ${file(userData/lambda.yml)}

  - serverless-offline
  service: users-service
  common: ${file(./../../../serverless.common.yml)}
  apiAuthorizer: ${self:custom.common.custom.apiAuthorizer.id}
  serverless-offline: ${self:custom.common.custom.serverless-offline}

In lines 4 and 15 of the Users service’s yaml (our demo service), you can see the configurations declared in the previous file being set in this service.


  handler: userData/index.handler
    - http:
        path: users/data
        method: get
        integration: lambda
          type: COGNITO_USER_POOLS
          authorizerId: ${self:custom.apiAuthorizer}
          origin: '*'
          headers: # <-- Specify allowed headers
            - Content-Type
            - Authorization

The configuration for the users/data endpoint (our test endpoint) is configured to return data if the Front End provides the authorizer that has been defined in lines 8-10.


					'use strict';

module.exports.handler = async(event, context, callback) => {
  const response = {
    statusCode: 200,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Credentials': true
    body: 'Hello World!! :D'
  callback(null, response);

Finally, this is the lambda that is executed when the end point has been called and the appropriate authorisation is provided.

The function returns a body of ‘Hello World!! ๐Ÿ˜€‘.


So that is it, the end of the 4 part tutorial series!!!!

I hope this has been helpful for you in understanding how to use Amazon Cognito on the Back End for Lambda functions in Serverless Framework.

Feel free to use the template I created for Wrapper.js to spin this up and give it a go!!

In the meantime, go build cool stuff and have fun ๐Ÿ˜€

Share this post