Lambda Authorizers to the Rescue
By: Nick Basinger
Tags: Api Gateway, Security, Amazon Web Services, Lambda, Cloud

A typical story: You want to build on AWS API Gateway so that your applications have highly scalable and managed REST APIs. You need a front door for your users or other applications to interact with your application. You need to authenticate your API, so you go with the default “out of the box” option: AWS_IAM. Everything is quickly set up and the POC works fine. You are ready to onboard your first user/service. But wait…

AWS API Gateway is a super simple and intuitive managed service by AWS that can super charge your entire serverless ecosystem. It is the microservice front door. It has it all. REST, Websocket, authentication, validation, the works. However, always using the default authentication method for your api gateway methods/resources could possibly create more issues for your teams and applications than solutions. It might be simpler out of the box, but it can end up tightly coupling all of your microservices and increasing unnecessary toil for your entire environment. There must be a better way!

Photo by Lester Hine on Unsplash

Whether your gamut of applications are same-account, cross-account, external to your company, etc., if you use the default way to secure your API’s on API Gateway each and every time, then you could be setting yourself up for an IAM nightmare. This is because in increasingly many scenarios IAM authentication requires cross-account role creation and management. This can reduce flexibility and cause extra toil the more complex your environment becomes. All too often the management becomes too overwhelming and teams can opt for less secure IAM policies and roles. This leads to greater and more frequent application coupling. To combat this potentially hazardous scenario, Lambda Authorizers come to the rescue.

Photo by Esteban Lopez on Unsplash

Lambda Authorizers, formerly called Custom Authorizers, are lambda functions you write and attach to your API methods to authenticate requests. You can choose your preferred programming language such as Nodejs or Python, and then write code as simple as a whitelist of applications or users allowed to access your API. The lambda can do whatever you want it to do. That is the power of lambda. Authenticate how exactly you need to, as long as the lambda returns either false (if the service/user shouldn’t have access), or a role with the correct permissions you wish to grant. Also, it’s free. You don’t get charged for the invoked lambda authorizer, and you can save costs by avoiding an unnecessary invoke of your downstream lambdas. As your validation/authentication logic evolves over time, you can update the lambda authorizer instead of adding additional code into your actual applications.

This is critical, and alongside the other powerful features of API Gateway, such as resource policies and json-schema validation of the request body, you have very flexible and powerful tools at your fingertips to up your serverless game. Here is an example where you specify a lambda authorizer in your serverless.yml file.

functions: myGreatFunction: handler: handler.hello events: - http: path: users method: get authorizer: myAuthorizer myAuthorizer: handler: handler.myAuthorizer

Using bearer token authentication, the lambda authorizer can verify the request, usually in the form of a JWT token, by calling AWS Cognito or another OAuth token provider, to ensure the user is who they say they are (Authentication/AuthN) and that they should have access to your API (Authorization/AuthZ).

There are two types of Lambda Authorizers to choose from: token-based and request parameter-based. Which one to choose depends on a few different factors. Token-based is the most straight forward choice. You choose one header that the lambda authorizer will validate the request with, like Authorization. Request parameter-based offers a lot more flexibility, by combining headers, query strings, etc. that all get passed into the lambda authorizer through the context parameter. You also have the ability to add additional information to the request from the Lambda Authorizer.

Regardless of which type you choose, you have a way to do some additional validation free-of-charge (remember, lambda authorizers don’t get charged for running). There is even the ability to cache lambda authorizer responses for a given amount of time to speed up the authentication/authorization of the incoming requests.

Photo by Luca Bravo on Unsplash

I have strongly enjoyed working with lambda authorizers. However, there are situations where the default is better. If you have only a few services that are in the same account that need to authenticate to each other via an API, then the default should be fine and is probably better. IAM gives you a powerfully easy way to authenticate out of the box. Below are the three main benefits, however, to using Lambda Authorizers instead of this default. These are important to keep in your mindset and vision as you create more and more APIs on API Gateway.

Check before you get charged. Lambda authorizers allow you to run code to authenticate, authorize, validate, or whatever you want to do (i.e. check the weather) before your lambda downstream ever gets invoked or charged. This helps with unnecessary requests that drown out your application that can cost unnecessary lambda invocations and wasted runtime. Gracefully enforce a decoupled infrastructure. With default IAM authentication on API Gateway, you are making a choice that can lead to some unintended consequences. A single account with 5 microservices is a lot different than an ecosystem with 200+ accounts and thousands of microservices. For cross account and external applications to gain access to your API, you will need to be granting these permissions directly into the account for each user/service/account on AWS IAM. Lambda authorizers can even connect to your current systems. As long as there is an accessible URL, the lambda authorizer can find it and use it to authenticate your requests. Keep your application code cleaner. As use-cases change and grow in complexity over time, using lambda authorizers to standardize how you authenticate and authorize will help over time. By separating your validation logic from your business logic, you are setting yourself up for easier business changes. Lambda Authorizers help standardize your microservice ecosystem communication by laying a foundation that is more conducive to a rapidly shifting environment. Even better, all of your microservices can use the same lambda authorizers, even from an account that is different then the account your API or application lambda is running in. That is definitely one of my favorite things about using lambda authorizers, second only to the fact that you get to write more lambda code! This allows you to uniformly update your authentication and authorization logic throughout larger groups of microservices in your environment all at the same time (different cache TTLs will effect that).

In absolute AWS fashion, we are able to customize the way we authenticate our APIs using actual Lambda functions. As your applications get more spread out and complex, better insight and more understanding into the problems that can arise from both types of authentication on API Gateway is extremely important. I have learned that it is definitely worth the initial effort of researching and planning which authentication method you want to choose for the long run, before you accidentally start rebuilding monoliths in the cloud.