Amazon API Gateway: Understanding Lambda Authorizers

In the first part of this blog series, we embarked on a comprehensive exploration of the fundamental features that make API Gateway an indispensable component in the AWS ecosystem. We delved into topics ranging from API creation and management to security, authentication, traffic control, request/response transformation, caching, monitoring, and analytics, just to name a few. In this blog post, we will delve into what Lambda Authorizers are, why they are essential, and how they can be implemented with a tutorial.

Gözde Yavuz
VNGRS
9 min readApr 3, 2024

--

AWS API Gateway is a powerful service that allows you to create, publish, and manage APIs at scale. When securing your APIs, authentication and authorization are crucial components. Lambda Authorizers play a pivotal role in enhancing the security of your API Gateway by enabling custom authorization logic.

What is a Lambda Authorizer?

A Lambda authorizer in AWS API Gateway is a serverless function (AWS Lambda function) that authenticates and authorizes incoming API requests. Unlike traditional API Gateway authorizers, such as Amazon Cognito or API Gateway custom authorizers, Lambda authorizers allow developers to implement custom logic for authentication and authorization.

© Amazon Web Services, Inc. or its Affiliates.

Here’s a detailed explanation of how Lambda authorizers enable this customization:

AWS Lambda Function: At the core of Lambda authorizers is an AWS Lambda function, which serves as the entry point for custom authentication and authorization logic. Developers write this function in their preferred programming language, such as Node.js, Python, Java, or others.

Request Context: Lambda authorizers receive the request context as an input parameter when they are invoked. This context includes information about the incoming API request, such as headers, query parameters, and request method. Developers can inspect these details to extract necessary information for authentication.

Token Validation: Developers can implement custom code within the Lambda function to validate authentication tokens or credentials sent with the API request. This step involves verifying the identity of the client making the request and ensuring the authenticity of the provided credentials.

Custom Authentication Logic: Lambda authorizers provide the flexibility to implement custom authentication processes tailored to the specific needs of the application. This could involve integrating with external identity providers, checking API keys, validating JWT tokens, or any other method suitable for the authentication requirements.

Authorization Decision: Based on the results of the authentication process, developers can programmatically make authorization decisions within the Lambda function. This involves determining whether the authenticated user or client has the necessary permissions to access the requested resource.

IAM Policy Generation: If the authentication and authorization are successful, the Lambda function generates an AWS Identity and Access Management (IAM) policy. This policy defines the permissions granted to the authenticated user or client. Developers have fine-grained control over the policy, specifying which AWS resources can be accessed and what actions are allowed.

Return Policy to API Gateway: The Lambda function returns the generated IAM policy to the API Gateway. The policy is then associated with the API Gateway method that the client is trying to access.

Enforcement by API Gateway: API Gateway enforces the IAM policy associated with the Lambda authorizer, ensuring that only authorized requests are allowed to proceed. If the policy grants the necessary permissions, the API Gateway allows the request to reach the backend resources.

How does it work?

© Amazon Web Services, Inc. or its Affiliates.

1. Client Sends Request: The process begins when a client sends a request to the API Gateway.

2. Lambda Authorizer is Triggered: The Lambda Authorizer, configured for the API Gateway, is triggered before the request reaches the backend. This function executes the authorization logic.

3. Authorization Logic Execution: The Lambda Authorizer executes the custom logic defined in the Lambda function. This could involve token validation, checking user roles, or any other logic needed for authorization.

4. Policy Generation: Based on the outcome of the authorization logic, the Lambda Authorizer generates an IAM policy that defines the permissions for the client.

5. Access Granted/Denied: The generated policy is then used to either grant or deny access to the API Gateway resources.

Key Components

Lambda Function: At the core of the Lambda authorizer is, unsurprisingly, an AWS Lambda function. This function is responsible for verifying the incoming request’s credentials and determining whether the client has the necessary permissions to access the requested resource.

Request and Token Handling : Lambda authorizers receive information from the incoming request, including headers, query parameters, and authentication tokens. Developers can implement custom logic to extract and validate these tokens or credentials.

Policy Generation: After successful authentication and authorization, the Lambda authorizer generates an IAM policy. This policy defines what actions the authenticated user or client is allowed to perform on AWS resources. The policy is then associated with the API Gateway method to enforce access control.

Why do we need Lambda Authorizers?

Custom Authorization Logic: One of the primary reasons for using Lambda Authorizers is the ability to implement custom authorization logic. Unlike built-in API Gateway authorization methods, Lambda Authorizers enable you to execute your own code to make decisions based on various factors such as user roles, permissions, or any other contextual information.

Scalability: Lambda Authorizers are highly scalable because they leverage AWS Lambda, which automatically scales based on demand. This makes them suitable for applications with varying workloads and ensures that your authorization logic can handle increased traffic without compromising performance.

Integration with External Systems: Lambda Authorizers can easily integrate with external identity providers or user databases. This allows you to incorporate existing authentication mechanisms and reuse user information from other systems, making it convenient to maintain a centralized identity management system.

Dynamic Authorization: Unlike static authorization policies, Lambda Authorizers enable dynamic decision-making. You can adjust access based on runtime conditions, ensuring that your API Gateway remains adaptable to changing requirements without the need for manual policy updates.

It’s time for the tutorial!

Prerequisites

  • AWS account setup.
  • Basic knowledge of AWS Lambda, AWS API Gateway, and IAM.

Step 1: We will create two lambda functions. The first one is for lambda authorization and the second one is a “hello-world” application for API’s integration response.

Log in to the AWS Management Console and navigate to the Lambda service. Create a new Lambda function for the application.

After the lambda is created, click the test button to test the application. You do not need to change simple index.js. That will be enough for our test application. You can configure the test event like below.

Click invoke. You will see the application returns like below.

Navigate to the Lambda functions again and click “Create function” button to create a lambda for the authorizer.

You can write a simple authorizer function that returns an IAM policy based on your requirements. Also, I have shared an example token based authorizer code from AWS below. Check the link for more details.

import json


def lambda_handler(event, context):
token = event['authorizationToken']
if token == 'allow':
print('authorized')
response = generatePolicy('user', 'Allow', event['methodArn'])
elif token == 'deny':
print('unauthorized')
response = generatePolicy('user', 'Deny', event['methodArn'])
elif token == 'unauthorized':
print('unauthorized')
raise Exception('Unauthorized') # Return a 401 Unauthorized response
return 'unauthorized'
try:
return json.loads(response)
except BaseException:
print('unauthorized')
return 'unauthorized' # Return a 500 error


def generatePolicy(principalId, effect, resource):
authResponse = {}
authResponse['principalId'] = principalId
if (effect and resource):
policyDocument = {}
policyDocument['Version'] = '2012-10-17'
policyDocument['Statement'] = []
statementOne = {}
statementOne['Action'] = 'execute-api:Invoke'
statementOne['Effect'] = effect
statementOne['Resource'] = resource
policyDocument['Statement'] = [statementOne]
authResponse['policyDocument'] = policyDocument
authResponse['context'] = {
"stringKey": "stringval",
"numberKey": 123,
"booleanKey": True
}
authResponse_JSON = json.dumps(authResponse)
return authResponse_JSON

Deploy the lambda function.

Step 2: We will set up an API Gateway.

Go to the API Gateway service in the AWS Management Console and create a new Rest API.

Create a resource and method for your API. Click the “Create resource” button and give your resource a name.

Here, you see the Proxy resource option and CORS options. I’ll be diving into the CORS option on AWS API Gateway next time but let me explain what “Proxy resource” means.

A proxy resource in AWS API Gateway is a wildcard that handles any path. It’s really useful for creating RESTful APIs with dynamic or unknown resource paths. When you send requests to a proxy resource, they are automatically directed to a designated backend integration, such as AWS Lambda or an HTTP endpoint. The best part is that you don’t need to define explicit resources for each path, which simplifies API configuration. When you send a request, the backend integration (whether it’s a Lambda function or an HTTP endpoint) receives the entire request and processes it based on the request path or other parameters.

After resource creation, click Create method button to create API methods. Api methods are simply http methods that you can define how you interact with the client responses.

On the method creation choose “GET” method as method type. And select the sample “hello-world” application that you created before. Save the method.

Click “Authorizers” on the left side menu.

Create the authorizer like below. Select the authorizer lambda that you created before.

Go to the API resource and choose the API method GET. Select “Method request” and click Edit.

Edit your method request as shown below.

After you save the method request, click “Deploy API” button on the resources page. And create a new stage to deploy the Api.

Now, you are ready to try it. Copy the invoke url and go to the endpoint. Also, you can use the template below to invoke your API.

https://restapi_id.execute-api.region.amazonaws.com/stage_name/

Conclusion

Lambda authorizers in AWS API Gateway offer a powerful solution for securing serverless applications by providing a customizable and scalable authentication and authorization mechanism. By leveraging the capabilities of AWS Lambda functions, developers can implement tailored security measures to meet the unique requirements of their applications. Understanding and effectively implementing Lambda authorizers is key to building robust and secure serverless architectures on AWS.

What is Next?

Now that I’ve covered the Lambda Authorizers groundwork, our next topic is Usage Plans on AWS Api Gateway. In the upcoming post, I will guide you through the process of building an API with a Usage Plan with a practical demonstration and deep dive explanation of it. See you in the next post!

--

--