An independent guide to building modern software for serverless and native cloud

Securing API Gateway with a Custom Authorizer

This tutorial references the code in the aws-connectedcar-dotnet-serverless repository. If you're new to this course, see the introduction for information about setting up your workstation and getting the sample code.

This third tutorial on securing API Gateway looks at the Vehicle API and its use of a custom authorizer. The Cognito authorizer that we covered in the previous tutorial comes pre-built to parse and validate the JWT access token from Cognito. With a custom authorizer, you take the same basic framework of an authorizer but apply it to a non-standard security mechanism.

Writing a Custom Authorizer

As we saw in the Working with Authorizers & Cognito lesson, an authorizer is simply a Lambda that validates supplied credentials, and in response outputs a JSON-formatted AuthPolicy.

Here’s the custom authorizer Lambda from the .Net variant of the sample code that's used for the Vehicle API:

Without going too far into Lambdas (which we'll be covering in the next section) you can see the outlines of how this authorizer works. The Vehicle API is expecting incoming requests to have vehicle VIN and pin numbers present in the HTTP headers as security credentials. To validate these credentials, this authorizer does the following:

  • Parses the two custom HTTP header values.
  • Calls the vehicle service to validate the credentials.
  • Returns a JSON policy document that either allows or denies the request.

Configuring a Custom Authorizer

The custom authorizer from the sample code checks the credentials with a simple query against the Vehicle table. So there’s nothing like the UserPool and UserPoolClient resources that need to be defined for Cognito. But we do need to define the resource for the authorizer Lambda, which is shown below:

We then need to specify this authorizer in the Vehicle API resource, as shown below:

The Auth element in this case specifies the VehicleAuthorizer, which is defined on lines 71-80, and contains elements for the SAM-specific LambdaRequestAuthorizer resource type.

Documentation for the LambdaRequestAuthorizer type can be found here: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-api-lambdarequestauthorizer.html

The “REQUEST” value set on Line 72 specifies that the Authorizer does not connect to an identity source. Lines 73-75 specify the ARN for the Lambda that we defined above. The Identity element on lines 76-79 is required when the FunctionPayloadType property has a “REQUEST” value. In this code it defines the two HTTP header names for the credentials, while line 80 specifies how long the results of a specific set of credentials will be cached before they’re reauthorized.

For the OpenAPI version of the Vehicle API, we need to define the Authorizer Lambda the same way, but there is no Auth element for the API resource. Instead, like with the Cognito Authorizer, you need to define a “securitySchemes” element in the vehicle.openapi.yaml OpenAPI specification:

Also, like we saw before with the Customer API and the Cognito Authorizer, there is a “security” element that needs to be added to each endpoint, as shown below on lines 26-27: