API Gateway provides a feature to limit the number of requests a client can make per second (rate) and per day/week/month (quota). Rate limiting is very useful to protect your system from resource starvation caused by a client flooding your system with requests. Quotas are more useful to protect against data scrapers or to limit the number of expensive operations a client can perform without paying appropriately.

You have to combine two features of API Gateway to implement rate limiting: Usage plans and API keys. API keys are used to identify the client while a usage plan defines the rate limit for a set of API keys and tracks their usage. Clients are expected to send the API key as the HTTP X-API-Key header. However, what about using a path parameter to identify the client like /v1/some-client-id/task or a query parameter like /v1/task?clientId=some-client-id ? In this article, you learn to use a Custom Authorizer to extract a parameter from the path and use the value as the API Key. You can follow the same approach to extract the API Key value from a query parameter or the body.

Keep in mind that there is a soft limit of 500 API keys. AWS will not raise this limit as high as you wish. The upper limit seems to be 10,000 API keys.

Custom Authorizer

A Custom Authorizer is implemented by a Lambda function to execute custom logic. Every request to the API Gateway first invokes the Custom Authorizer. The Custom Authorizer returns an access policy ( policyDocument ) and the API key value ( usageIdentifierKey ). API Gateway takes the result from the Custom Authorizer, checks if the API key exists and if the client is allowed to make the request according to the access policy.

Create the Lambda function:

Author a Lambda function from scratch

Set a Name Set the Runtime to Node.js 8.10 Set Role to Create a new role from one or more templates to create a new IAM role for the Lambda function Set a Role Name Click Create function to save

The following Lambda function code uses the value of the path parameter clientId as the API key value and allows access to all API resources and methods.

exports.handler = async (event) => {

if ( 'pathParameters' in event && 'clientId' in event.pathParameters) {

return {

principalId: event.pathParameters.clientId,

policyDocument: {

Version: '2012-10-17' ,

Statement: [{

Action: 'execute-api:Invoke' ,

Effect: 'Allow' ,

Resource: `arn:aws:execute-api:us-east-1:*: ${event.requestContext.apiId} /*`

}]

},

usageIdentifierKey: event.pathParameters.clientId

};

} else {

throw new Error ( 'path parameter clientId missing' );

}

};



Once the Lambda function is in place you can create the Custom Authorizer in API Gateway:

Set a Name Select the Lambda Function you created earlier

Set the Lambda Event Payload to Request Set the Identity Sources to Context apiId Disable Authorization Caching Click Create to save You are asked to grant permissions



Unfortunately, you can not use a path parameter as an Identity Source. We use the API id which is the same for all requests. Therefore, it is important to disable Authorization Caching. Otherwise, all requests (no matter what path parameter used) would use the same API key value from the cached authorizer response. Confusingly, a query parameter is valid Identity Source.

Configuring API Gateway