Skip to main content

How to secure an API using Lambda authorizer

Greetings!

I wrote about creating a CRUD API using API Gateway and Lambda in a previous article. However, I did not talk about how to secure it. In this article, I am going to explain how we can use Lamda Authorizer to secure an API.

The complete code is here.

Lambda Authorizer

Lambda authorizer is an API gateway feature to control access to your API. It uses the provided lambda function to do so. This is useful when we want to implement a custom authorization scheme that uses a bearer token (JWT) or a request parameter.
  • Token authorizer - uses a token to authorize uses. It receives the caller's identity in a bearer token, such as a JSON Web Token (JWT) or an OAuth token
  • Request authorizer - uses parameters, headers, and query strings to pass user identity

In this article, we use a token-based authorizer. For simplicity, we expect our token to be "cat".

Initialize the project

Let's initialize the project using the serverless framework.
mkdir api-gateway-lambda-authorizer
cd api-gateway-lambda-authorizer
serverless create --template aws-nodejs
npm init -y
Enable ES6 modules as well in package.json.
{
  "name": "api-gateway-lambda-authorizer",
  "version": "1.0.0",
  "author": "Manjula Jayawardana",
  "description": "Secure API using lambda authorizer",
  "main": "handler.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "license": "ISC"
}

Create the lambda

First of all, let's create our lambda backend service. It is nothing but a simple string message.
"use strict";

export const handler = async (event) => {
  console.log("notes get calles with", JSON.stringify(event));
  return {
    statusCode: 200,
    body: JSON.stringify({
      message: "Go Lambda! Your function executed successfully!",
    }),
  };
};

Define the endpoint

Let's define our endpoint next. We do this without any security.
service: api-gateway-lambda-authorizer
frameworkVersion: '3'

provider:
  name: aws
  runtime: nodejs16.x
  stage: dev
  region: us-east-1

functions:
  getNotes:
    handler: src/notes.handler
    events:
    - http:
        path: /notes
        method: get
        cors: true
Deploy and test what we have done so far.
serverless deploy
curl https://a5fnecnuof.execute-api.us-east-1.amazonaws.com/dev/notes 
With it done, it is time to introduce our authorizer function.

Create authorizer Lambda

Now, let's create our authorizer lambda function. We have a new function named notedAuthorizer. We then assign that to the authorizer property in http event section.
Change your serverless.yml as below.
functions:
  getNotes:
    handler: src/notes.handler
    events:
    - http:
        path: /notes
        method: get
        cors: true
        authorizer: notesAuthorizer

  notesAuthorizer:
    handler: src/authorizer.handler
Create a new file authorizer.js under the src folder and add the following code.
touch src/authorizer.js
export const handler = async function (event) {
  console.log("authorizer get called with", JSON.stringify(event));
  if (event.authorizationToken === "cat") {
    return {
      principalId: "poos",
      policyDocument: {
        Version: "2012-10-17",
        Statement: [
          {
            Action: "execute-api:Invoke",
            Effect: "Allow",
            Resource: event.methodArn,
          },
        ],
      },
    };
  }
  throw Error("Unauthorized");
};
We can retrieve the token using "authorizationToken" property that comes with the event for this scenario. As our token is "cat", we check its equality with the "cat" string. If it's true, we need to return the policy document that includes allowing effect for API gateway invoke action. Also, note that we can retrieve method arn from even.tmethodArn. If the condition fails, we throw an error.
Deploy the new changes and let's visit the AWS console.

Go to API Gateway, and you should able to see notes resource is created. When you click on it, you can see that for Auth, notesAuthorizer is assigned.

Now, click on the Authorizers menu. You could see our authorizer details there. Have a note that "Lambda Event Payload" is "Token" and "Token Source" is "Authorization".


Let's try to invoke the /notes endpoint again. Add "dog" as Authorization. You should be able to see the unauthorized error now.


Now, again invoke the endpoint using "cat" as Authorization. This time, it should work.


Conclusion

In this article, we have learned how we can use the lambda authorizer feature of AWS API Gateway to secure an API. We have used a hard-coded value for the purpose of the article.

Comments