Authenticate Lambda Requests with ALB and Google OAuth: Part 2

Authenticate Lambda requests with an Application Load Balancer with Infrastructure as Code.

General Architecture
  1. Create an Application Load Balancer using IaC
  2. Format Lambda responses
  3. Add an Alias Record to our Route53 domain that directs traffic to our ALB.
  4. Test our application.

Set OAuth Client and Certificate ARN environment variables.

If you forgot to save your Google Client ID and Client Secret during the previous post, don’t panic! Just go back to your Google API Console Credentials page and navigate to your project. Select the “Credentials” tab and your credentials will be available in plain text at the top right of the page.

Google ClientID and Client Secret
GOOGLE_WEB_FORUM_CLIENT_ID=<your_client_id>
GOOGLE_WEB_FORUM_CLIENT_SECRET=<your_client_secret>
SSL_CERTIFICATE=<your_certificate_arn>

Serverless Template

First things first, we need to create an Application Load Balancer resource and a “Listener” for that load balancer. The listener is the resource that will listen for requests made to the load balancer and direct them to the proper endpoint.

CloudFormation Resources

In the Resources section of our serverless.yaml file, we will need to add the following resources:

  1. The LoadBalancer resource’s type is set to Application by default.
  2. The ${env:VAR} notation is used within the serverless framework to reference the variables in the .env file at build time.
  3. To create an HTTPS listener, we need to provide a TLS certificate with which it can authenticate requests.
  4. The listener for our ALB has the PORT property set to 443 and PROTOCOL property set to HTTPS — this is what distinguishes our load balancer as an HTTPS ALB.

Create a serverless “authorizer”

To enable authentication with our OIDC-compliant OAuth provider on our Lambda services, we can leverage some of the syntactic sugar provided by the serverless framework. First, we’ll set up an Application Load Balancer “authorizer” object in the provider section of the template.

Attach ALB events to our Lambda services

Finally, all that’s left is to actually use our GoogleAuth authorizer to authenticate requests made to Lambda services.

Format Lambda Responses and Errors

Whether you want to return a response or an exception from your Lambda, it is extremely important that it is formatted correctly (or else your user will receive a 502 Bad Gateway response).

Returning Successful Responses

When returning a general response from your Lambda, there are a few properties that the ALB will expect to be defined within the response object.

  • statusDescription (string) — [REQUIRED]: A combination of the HTTP status code and the code’s description (i.e. 200 OK, 404 Not Found, etc.)
  • headers (object) — [REQUIRED]: Even if the headers object is empty, it must be defined on the response. However, in most cases your response body will contain a JSON Object and you will need to define the following key/value pair within the headers object: { 'Content-Type': 'application/json' }.
  • isBase64Encoded (bool) — [REQUIRED]: Whether or not your response is base64 encoded.
  • body (string) — [REQUIRED]: The data that you will return from your Lambda service.
  • multiValueHeaders (object) — [CONDITIONAL]: If you enabled multiValueHeaders on your ALB Target Group, you must return a multiValueHeaders object in your Lambda response, even if it’s empty.

Returning Errors

The format for errant responses is slightly different that that of successful responses. The following function will format an error that is caught while handling a request and return it back to the ALB.

  1. The 'Content-Type' for the response is set to 'text/plain' because the body of the response is just a string.
ConditionalCheckFailedException: Forum, "Secure Forum", already exists.

Create a Route53 Alias Record that routes traffic to the Application Load Balancer

If you have cloned the tutorial code, you can simply run the following command to build the TypeScript project and deploy it to AWS.

$ yarn build-deploy
  1. Click on Hosted Zones.
  2. Select the Domain you want to use for this project.
  3. Select Create Record.
  4. Select “Alias”
  5. Drop down the Choose Endpoint dropbox and select “Alias to Application and Classic Load Balancer.
  6. Choose the AWS Region to which you deployed the serverless stack.
  7. When you click on the Load Balancer dropdown box, you will be presented with all of the Application and Classic Load Balancers you have deployed to this region. Select the option that starts with “dualstack.” and ends with your Load Balancer’s DNS name.
  8. Click Create Records.
Create an A Record for the Application Load Balancer

Test Your ALB-Authenticated Services!

JSON-formatted response for the request

Additions

At some point in the near future, I’ll post 2 related articles. One will address how we can unpack the JSON Web Tokens provided in the request header with NodeJS in order to access the “scoped” information from the OIDC client (name, email, etc.). The other article will explain how we can configure Postman to make authenticated requests to our ALB.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store