Use API Gateway Custom Authorizers
An Amazon API Gateway custom authorizer is a Lambda function that you provide to control access to your API methods. A custom authorizer uses bearer token authentication strategies, such as OAuth or SAML. It can also use information described by headers, paths, query strings, stage variables, or context variables request parameters.
Note
Path parameters can be used to grant or deny permissions to invoke a method, but they cannot be used to define identity sources, which can be used as parts of an authorization policy caching key. Only headers, query strings, stage variables, and context variables can be set as identity sources.
When a client calls your API, API Gateway verifies whether a custom authorizer is
configured for the API method. If so, API Gateway calls the Lambda function. In this
call, API Gateway
supplies the authorization token that is extracted from a specified request header
for the
token-based authorizer, or passes in the incoming request parameters as the input
(for
example, the event parameter) to the request parameters-based authorizer
function.
You can implement various authorization strategies, such as JSON Web Token (JWT) verification and OAuth provider callout. You can also implement a custom scheme based on incoming request parameter values, to return IAM policies that authorize the request. If the returned policy is invalid or the permissions are denied, the API call does not succeed. For a valid policy, API Gateway caches the returned policy, associated with the incoming token or identity source request parameters. It then uses the cached policy for the current and subsequent requests, over a pre-configured time-to-live (TTL) period of up to 3600 seconds. You can set the TTL period to zero seconds to disable the policy caching. The default TTL value is 300 seconds. Currently, the maximum TTL value of 3600 seconds cannot be increased.
Topics
- Types of API Gateway Custom Authorizers
- Create an API Gateway Custom Authorizer Lambda Function
- Input to an Amazon API Gateway Custom Authorizer
- Output from an Amazon API Gateway Custom Authorizer
- Configure Custom Authorizer Using the API Gateway Console
- Call an API with API Gateway Custom Authorizers
Types of API Gateway Custom Authorizers
API Gateway supports custom authorizers of the TOKEN and REQUEST types:
-
Custom authorizers of the
TOKENtype grant a caller permissions to invoke a given request using an authorization token passed in a header. The token could be, for example, an OAuth token. -
Custom authorizers of the
REQUESTtype grant a caller permissions to invoke a given request using request parameters, including headers, query strings, stage variables, or context parameters.
Create an API Gateway Custom Authorizer Lambda Function
Before creating an API Gateway custom authorizer, you must first create the AWS Lambda function that implements the logic to authorize and, if necessary, to authenticate the caller. You can do so in the Lambda console, using the code template available from the API Gateway Custom Authorizer blueprint. Or you can create one from scratch, following this example in awslabs. For illustration purposes, we explain how to create a simple Lambda function from scratch without using a blueprint. In production code, you should follow the API Gateway Custom Authorizer blueprint to implement your authorizer Lambda function.
When creating the Lambda function for your API Gateway custom authorizer, you assign
an
execution role for the Lambda function if it calls other AWS services. For the
following example, the basic AWSLambdaRole suffices. For more involved use
cases, follow the instructions to grant permissions in an execution role for the Lambda
function.
Create a Lambda Function of a Custom Authorizer of the TOKEN type
In the code editor of the Lambda console, enter the following Node.js code as an
example of the API Gateway custom authorizer of the TOKEN type.
Copy// A simple TOKEN authorizer example to demonstrate how to use an authorization token // to allow or deny a request. In this example, the caller named 'user' is allowed to invoke // a request if the client-supplied token value is 'allow'. The caller is not allowed to invoke // the request if the token value is 'deny'. If the token value is 'Unauthorized', the function // returns the 'Unauthorized' error with an HTTP status code of 401. For any other token value, // the authorizer returns an 'Invalid token' error. exports.handler = function(event, context, callback) { var token = event.authorizationToken; switch (token.toLowerCase()) { case 'allow': callback(null, generatePolicy('user', 'Allow', event.methodArn)); break; case 'deny': callback(null, generatePolicy('user', 'Deny', event.methodArn)); break; case 'unauthorized': callback("Unauthorized"); // Return a 401 Unauthorized response break; default: callback("Error: Invalid token"); } }; // Help function to generate an IAM policy var generatePolicy = function(principalId, effect, resource) { var authResponse = {}; authResponse.principalId = principalId; if (effect && resource) { var policyDocument = {}; policyDocument.Version = '2012-10-17'; policyDocument.Statement = []; var statementOne = {}; statementOne.Action = 'execute-api:Invoke'; statementOne.Effect = effect; statementOne.Resource = resource; policyDocument.Statement[0] = statementOne; authResponse.policyDocument = policyDocument; } // Optional output with custom properties of the String, Number or Boolean type. authResponse.context = { "stringKey": "stringval", "numberKey": 123, "booleanKey": true }; return authResponse; }
For custom authorizers of the TOKEN type, API Gateway passes the
source token to the Lambda function as the event.authorizationToken.
Based on the value of this token, the preceding authorizer function returns an
Allow IAM policy on a specified method if the token value is
'allow'. This permits a caller to invoke the specified method. The
caller receives a 200 OK response. The authorizer function returns a
Deny policy against the specified method if the authorization token
has a 'deny' value. This blocks the caller from calling the method. The
client receives a 403 Forbidden response. If the token is
'unauthorized', the client receives a 401 Unauthorized
response. If the token is 'fail' or anything else, the client receives
a 500 Internal Server Error response. In both of the last two cases, no
IAM policy is generated and the calls fail.
Note
In production code, you may need to authenticate the user before granting authorizations. If so, you can add authentication logic in the Lambda function as well. Consult the provider-specific documentation for instructions on how to call such an authentication provider.
In addition to returning an IAM policy, the custom authorizer function must
also return the caller's principal identifier. It can optionally return a key-value
map named context, containing additional information that can be passed
into the integration backend. For more information about the authorizer's output
format, see Output from an Amazon API Gateway Custom
Authorizer.
You can use the context map to return cached credentials from
the authorizer to the backend, using an integration request mapping template. This
enables the backend to provide an improved user experience by using the cached
credentials to reduce the need to access the secret keys and open the authorization
tokens for every request.
For the Lambda proxy integration, API Gateway passes the context object
from a custom authorizer directly to the backend Lambda function as part of the input
event. You can retrieve the context key-value pairs in
the Lambda function by calling
$event.requestContext.authorizer..
For the preceding custom authorizer example, keykey is
stringKey, numberKey, or booleanKey.
Their values are stringified, for example, "stringval",
"123", or "true", respectively.
Before going further, you may want to test the Lambda function from within the Lambda
console. To do this, configure the sample event to provide an input as described in
Input to an Amazon API Gateway Custom
Authorizer and verify the result by examining the output compatible with Output from an Amazon API Gateway Custom
Authorizer. The next subsection explains how to create a Lambda function of the Request authorizer.
Create a Lambda Function of a Custom Authorizer of the REQUEST type
In the code editor of the Lambda console, enter the following Node.js code for a
simplified Lambda function as an example of the API Gateway custom authorizers of
the
REQUEST type.
Copyexports.handler = function(event, context, callback) { console.log('Received event:', JSON.stringify(event, null, 2)); // A simple REQUEST authorizer example to demonstrate how to use request // parameters to allow or deny a request. In this example, a request is // authorized if the client-supplied HeaderAuth1 header, QueryString1 query parameter, // stage variable of StageVar1 and the accountId in the request context all match // specified values of 'headerValue1', 'queryValue1', 'stageValue1', and // '123456789012', respectively. // Retrieve request parameters from the Lambda function input: var headers = event.headers; var queryStringParameters = event.queryStringParameters; var pathParameters = event.pathParameters; var stageVariables = event.stageVariables; var requestContext = event.requestContext; // Parse the input for the parameter values var tmp = event.methodArn.split(':'); var apiGatewayArnTmp = tmp[5].split('/'); var awsAccountId = tmp[4]; var region = tmp[3]; var restApiId = apiGatewayArnTmp[0]; var stage = apiGatewayArnTmp[1]; var method = apiGatewayArnTmp[2]; var resource = '/'; // root resource if (apiGatewayArnTmp[3]) { resource += apiGatewayArnTmp[3]; } // Perform authorization to return the Allow policy for correct parameters and // the 'Unauthorized' error, otherwise. var authResponse = {}; var condition = {}; condition.IpAddress = {}; if (headers.HeaderAuth1 === "headerValue1" && queryStringParameters.QueryString1 === "queryValue1" && stageVariables.StageVar1 === "stageValue1" && requestContext.accountId === "123456789012") { callback(null, generateAllow('me', event.methodArn)); } else { callback("Unauthorized"); } } // Help function to generate an IAM policy var generatePolicy = function(principalId, effect, resource) { // Required output: var authResponse = {}; authResponse.principalId = principalId; if (effect && resource) { var policyDocument = {}; policyDocument.Version = '2012-10-17'; // default version policyDocument.Statement = []; var statementOne = {}; statementOne.Action = 'execute-api:Invoke'; // default action statementOne.Effect = effect; statementOne.Resource = resource; policyDocument.Statement[0] = statementOne; authResponse.policyDocument = policyDocument; } // Optional output with custom properties of the String, Number or Boolean type. authResponse.context = { "stringKey": "stringval", "numberKey": 123, "booleanKey": true }; return authResponse; } var generateAllow = function(principalId, resource) { return generatePolicy(principalId, 'Allow', resource); } var generateDeny = function(principalId, resource) { return generatePolicy(principalId, 'Deny', resource); }
This Lambda function of the REQUEST authorizer verifies the input
request parameters to return an Allow IAM policy on a specified
method if all the required parameter (HeaderAuth1,
QueryString1, StageVar1, and accountId)
values match the pre-configured ones. This permits a caller to invoke the specified
method. The caller receives a 200 OK response. Otherwise, the
authorizer function returns an Unauthorized error, without generating
any IAM policy.
The above example authorizer function in Node.js illustrates the programming flow
to create a custom authorizer of the REQUEST type, including parsing
the input which is similar to parsing the Lambda function input
in the Lambda proxy integration, You can extend the implementation to
other languages supported by Lambda, such as Java or Python. For example to parse
the
input to a custom REQUEST authorizer in Java, see Java Function
for an API with Lambda Proxy Integration.
Before going further, you may want to test the Lambda function from within the Lambda console. To do this, configure the sample event to provide the input and verify the result by examining the output. The next two sections explain the Input to an Amazon API Gateway Custom Authorizer and Output from an Amazon API Gateway Custom Authorizer.
Input to an Amazon API Gateway Custom Authorizer
For a custom authorizer of the TOKEN type, you must specify a custom
header as the Token Source when you configure the authorizer for
your API. The API client must pass the required authorization token in the incoming
request. Upon receiving the incoming method request, API Gateway extracts the token
from the
custom header. It then passes the token as the authorizationToken property
of the event object of the Lambda function, in addition to the method ARN as
the methodArn property:
Copy{ "type":"TOKEN", "authorizationToken":"<caller-supplied-token>", "methodArn":"arn:aws:execute-api:<regionId>:<accountId>:<apiId>/<stage>/<method>/<resourcePath>" }
In this example, the type property specifies the authorizer type, which
is a TOKEN authorizer. The
originates
from the custom authorization header in a client request. The <caller-supplied-token>methodArn is
the ARN of the incoming method request and is populated by API Gateway in accordance
with the
custom authorizer configuration.
For the example TOKEN authorizer Lambda function shown in the preceding
section, the <caller-supplied-token> string is
allow, deny, unauthorized, or any other
string value. An empty string value is the same as unauthorized. The
following shows an example of such an input to obtain an Allow policy on
the GET method of an API (ymy8tbxw7b) of the AWS account
(123456789012) in any stage (*).
Copy{ "type":"TOKEN", "authorizationToken":"allow", "methodArn":"arn:aws:execute-api:us-west-2:123456789012:ymy8tbxw7b/*/GET/" }
For a custom authorizer of the REQUEST type, API Gateway passes the required
request parameters to the authorizer Lambda function as part of the event
object. The affected request parameters include headers, path parameters, query string
parameters, stage variables, and some of request context variables. The API caller
can
set the path parameters, headers, and query string parameters. The API developer must
set the stage variables during the API deployment and API Gateway provides the request
context
at run time.
The following example shows an input to a REQUEST authorizer for an API
method (GET /request) with a proxy integration:
Copy{ "type": "REQUEST", "methodArn": "arn:aws:execute-api:us-east-1:123456789012:s4x3opwd6i/test/GET/request", "resource": "/request", "path": "/request", "httpMethod": "GET", "headers": { "X-AMZ-Date": "20170718T062915Z", "Accept": "*/*", "HeaderAuth1": "headerValue1", "CloudFront-Viewer-Country": "US", "CloudFront-Forwarded-Proto": "https", "CloudFront-Is-Tablet-Viewer": "false", "CloudFront-Is-Mobile-Viewer": "false", "User-Agent": "...", "X-Forwarded-Proto": "https", "CloudFront-Is-SmartTV-Viewer": "false", "Host": "....execute-api.us-east-1.amazonaws.com", "Accept-Encoding": "gzip, deflate", "X-Forwarded-Port": "443", "X-Amzn-Trace-Id": "...", "Via": "...cloudfront.net (CloudFront)", "X-Amz-Cf-Id": "...", "X-Forwarded-For": "..., ...", "Postman-Token": "...", "cache-control": "no-cache", "CloudFront-Is-Desktop-Viewer": "true", "Content-Type": "application/x-www-form-urlencoded" }, "queryStringParameters": { "QueryString1": "queryValue1" }, "pathParameters": {}, "stageVariables": { "StageVar1": "stageValue1" }, "requestContext": { "path": "/request", "accountId": "123456789012", "resourceId": "05c7jb", "stage": "test", "requestId": "...", "identity": { "apiKey": "...", "sourceIp": "..." }, "resourcePath": "/request", "httpMethod": "GET", "apiId": "s4x3opwd6i" } }
The requestContext is a map of key-value pairs and corresponds to the
$context variable. Its outcome is
API-dependent. API Gateway may add new keys to the map. For more information about
the Lambda
function input in a proxy integration, see Input Format of a Lambda
Function for Proxy Integration
.
Output from an Amazon API Gateway Custom Authorizer
The custom authorizer's Lambda function returns an output that must include the
principal identifier (principalId) and a policy document
(policyDocument) containing a list of policy statements. The output can
also include a context map containing key-value pairs. The following shows
an example of this output.
Copy{ "principalId": "yyyyyyyy", // The principal user identification associated with the token sent by the client. "policyDocument": { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": "Allow|Deny", "Resource": "arn:aws:execute-api:{regionId}:{accountId}:{appId}/{stage}/{httpVerb}/[{resource}/{httpVerb}/[...]]" } ] }, "context": { "stringKey": "value", "numberKey": "1", "booleanKey": "true" } }
Here, a policy statement stipulates whether to allow or deny (Effect)
the API Gateway execution service to invoke (Action) the specified API method
(Resource). You can use a wild card (*) to specify a
resource type (method). For information about setting valid policies for calling an
API,
see Statement Reference of IAM
Policies for Executing API in API Gateway.
For an authorization-enabled method AR, e.g.,
arn:aws:execute-api:{region-id}:{account-id}:{api-id}/{stage-id}/{method}/{resource}/{path},
the maximum length is 1600 bytes. The path parameter values, the size of which are
determined at run time, can cause the ARN length to exceed the limit. When this happens,
the API client will receive a 414 Request URI too long response.
In addition, the Resource ARN, as shown in the policy statement output by the authorizer, is currently limited to 512 characters long. For this reason, you must not use URI with a JWT token of a significant length in a request URI. You can safely pass the JWT token in a request header, instead.
You can access the principalId value in a mapping template using the
$context.authorizer.principalId variable. This is useful if you want to
pass the value to the backend. For more information, see Accessing the $context Variable.
You can access the stringKey, numberKey, or
booleanKey value (for example, "value", "1",
or "true") of the context map in a mapping template by calling
$context.authorizer.stringKey,
$context.authorizer.numberKey, or
$context.authorizer.booleanKey, respectively. The returned values are
all stringified. Notice that you cannot set a JSON object or array as a valid value
of
any key in the context map.
The following shows example output from the example custom authorizer. The example
output contains a policy statement to block (Deny) calls to the
GET method in an API (ymy8tbxw7b) of an AWS account
(123456789012) in any stage (*).
Copy{ "principalId": "user", "policyDocument": { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": "Deny", "Resource": "arn:aws:execute-api:us-west-2:123456789012:ymy8tbxw7b/*/GET/" } ] } }
Configure Custom Authorizer Using the API Gateway Console
After you create the Lambda function and verify that it works, use the following steps to configure the API Gateway custom authorizer in the API Gateway console.
To enable a custom authorizer on API methods
-
Sign in to the API Gateway console.
-
Create a new or select an existing API and choose Authorizers under that API.
-
Choose Create New Authorizer.
-
For Create Authorizer, type an authorizer name in the Name input field.
-
For Type, choose the Lambda option.
-
For Lambda Function, choose a region and then choose an available custom authorizer's Lambda function.
-
Leave Lambda Execution Role blank to let the API Gateway console set a resource-based policy. The policy grants API Gateway permissions to invoke the authorizer Lambda function. You can also choose to type the name of an IAM role to allow API Gateway to invoke the authorizer Lambda function. For an example of such a role, see Set Up an IAM Role and Policy for an API to Invoke Lambda Functions.
If you choose to let the API Gateway console set the resource-based policy, the Add Permission to Lambda Function dialog is displayed. Choose OK. After the custom authorization is created, you can test it with appropriate authorization token values to verify that it works as expected.
-
For Lambda Event Payload, choose either Token for a
TOKENauthorizer or Request for aREQUESTauthorizer. (This is the same as setting the type property toTOKENorREQUEST.) -
Depending on the choice of the previous step, do one of the following:
-
For the Token options, do the following:
-
Type the name of a header in Token Source. The API client must include a header of this name to send the authorization token to the custom authorizer.
-
Optionally, provide a RegEx statement in
Token Validationinput field. API Gateway performs initial validation of the input token against this expression and invokes the authorizer upon successful validation. This helps reduce chances of being charged for invalid tokens. -
For Authorization Caching, select or clear the Enabled option, depending on whether you want to cache the authorization policy generated by the authorizer or not. When policy caching is enabled, you can choose to modify the TTL value from the default (300). Setting TTL=0 disables policy caching. When policy caching is enabled, the header name specified in Token Source becomes the cache key.
-
-
For the Request option, do the following:
-
For Identity Sources, type a request parameter name of a chosen parameter type. Supported parameter types are
Header,Query String,Stage Variable, andContext. To add more identity sources, choose Add Identity Source.API Gateway uses the specified identity sources as the request authorizer caching key. When caching is enabled, API Gateway calls the authorizer's Lambda function only after successfully verifying that all the specified identity sources are present at runtime. If a specified identify source is missing, null, or empty, API Gateway returns a
401 Unauthorizedresponse without calling the authorizer Lambda function.When multiple identity sources are defined, they all used to derive the authorizer's cache key. Changing any of the cache key parts causes the authorizer to discard the cached policy document and generate a new one.
-
For Authorization Caching, select or deselect the Enabled option, depending on whether you want to cache the authorization policy generated by the authorizer or not. When policy caching is enabled, you can choose to modify the TTL value from the default (300). Setting TTL=0 disables policy caching.
When caching is disabled, it is not necessary to specify an identity source. API Gateway does not perform any validation before invoking the authorizer's Lambda function.
-
Note
To enable caching, your authorizer must return a policy that is applicable to all methods across an API. To enforce method-specific policy, you can set the TTL value to zero to disable policy caching for the API.
-
-
Choose Create to create the new custom authorizer for the chosen API.
-
After the authorizer is created for the API, you can optionally test invoking the authorizer before it is configured on a method.
For the
TOKENauthorizer, type a valid token in the Identity token input text field and the choose Test. The token will be passed to the Lambda function as the header you specified in the Identity token source setting of the authorizer.For the
REQUESTauthorizer, type the valid request parameters corresponding to the specified identity sources and then choose Test.In addition to using the API Gateway console, you can use AWS CLI or an AWS SDK for API Gateway to test invoking an authorizer. To do so using the AWS CLI, see test-invoke-authorizer.
Note
Test-invoke for method executions test-invoke for authorizers are independent processes.
To test invoking a method using the API Gateway console, see Use the Console to Test a Method. To test invoking a method using the AWS CLI, see test-invoke-method.
To test invoking a method and a configured authorizer, deploy the API, and then use cURL or Postman to call the method, providing the required token or request parameters.
The next procedure shows how to configure an API method to use the custom authorizer.
To configure an API method to use a custom authorizer
-
Go back to the API. Create a new method or choose an existing method. If necessary, create a new resource.
-
In Method Execution, choose the Method Request link.
-
Under Settings, expand the Authorization drop-down list to select the custom authorizer you just created (for example, myTestApiAuthorizer), and then choose the check mark icon to save the choice.
-
Optionally, while still on the Method Request page, choose Add header if you also want to pass the custom authorization token to the backend. In Name, type a custom header name that matches the Token Source name you specified when you created the custom authorizer for the API. Then, choose the check mark icon to save the settings. This step does not apply to
REQUESTauthorizers. -
Choose Deploy API to deploy the API to a stage. Note the Invoke URL value. You need it when calling the API. For a
REQUESTauthorizer using stage variables, you must also define the required stage variables and specify their values while in Stage Editor.
Call an API with API Gateway Custom Authorizers
Having configured the custom authorizer and deployed the API, you should test the API with the custom authorizer enabled. For this, you need a REST client, such as cURL. Postman. For the following examples, we use Postman.
Note
When calling an authorizer-enabled method, API Gateway does not log the call to CloudWatch
if
the required token for the TOKEN authorizer is not set, null, or
invalidated by the specified Token validation expression.
Similarly, API Gateway does not log the call to CloudWatch if any of the required
identity
sources for the REQUEST authorizer are not set, null or empty.
In the following, we show how to use Postman to call or test the API with the
previously described custom TOKEN authorizer enabled. The method can be
applied to calling an API with a custom REQUEST authorizer, if you specify
the required path, header, or query string parameters explicitly.
To call an API with the custom TOKEN authorizer
-
Open Postman, choose the GET method, and paste the API's Invoke URL into the adjacent URL field.
Add the custom authorization token header and set the value to
allow. Choose Send.
The response shows that the API Gateway custom authorizer returns a 200 OK response and successfully authorizes the call to access the HTTP endpoint (http://httpbin.org/get) integrated with the method.
-
Still in Postman, change the custom authorization token header value to
deny. Choose Send.
The response shows that the API Gateway custom authorizer returns a 403 Forbidden response without authorizing the call to access the HTTP endpoint.
-
In Postman, change the custom authorization token header value to
unauthorizedand choose Send.
The response shows that API Gateway returns a 401 Unauthorized response without authorizing the call to access the HTTP endpoint.
-
Now, change the custom authorization token header value to
fail. Choose Send.
The response shows that API Gateway returns a 500 Internal Server Error response without authorizing the call to access the HTTP endpoint.


