Menu
Amazon API Gateway
Developer Guide

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.


                    API Gateway custom authorization workflow

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.

Types of API Gateway Custom Authorizers

API Gateway supports custom authorizers of the TOKEN and REQUEST types:

  • Custom authorizers of the TOKEN type 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 REQUEST type 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.key. For the preceding custom authorizer example, key 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.

Copy
exports.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 <caller-supplied-token> originates from the custom authorization header in a client request. The 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

  1. Sign in to the API Gateway console.

  2. Create a new or select an existing API and choose Authorizers under that API.

  3. Choose Create New Authorizer.

  4. For Create Authorizer, type an authorizer name in the Name input field.

  5. For Type, choose the Lambda option.

  6. For Lambda Function, choose a region and then choose an available custom authorizer's Lambda function.

  7. 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.

  8. For Lambda Event Payload, choose either Token for a TOKEN authorizer or Request for a REQUEST authorizer. (This is the same as setting the type property to TOKEN or REQUEST.)

  9. Depending on the choice of the previous step, do one of the following:

    1. 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 Validation input 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.

    2. 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, and Context. 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 Unauthorized response 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.

  10. Choose Create to create the new custom authorizer for the chosen API.

  11. After the authorizer is created for the API, you can optionally test invoking the authorizer before it is configured on a method.

    For the TOKEN authorizer, 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 REQUEST authorizer, 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

  1. Go back to the API. Create a new method or choose an existing method. If necessary, create a new resource.

  2. In Method Execution, choose the Method Request link.

  3. 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.

  4. 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 REQUEST authorizers.

  5. Choose Deploy API to deploy the API to a stage. Note the Invoke URL value. You need it when calling the API. For a REQUEST authorizer 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

  1. 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.

    
                            Call API with Custom Authorization Allow Token

    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.

  2. Still in Postman, change the custom authorization token header value to deny. Choose Send.

    
                            Call API with Custom Authorization Deny Token

    The response shows that the API Gateway custom authorizer returns a 403 Forbidden response without authorizing the call to access the HTTP endpoint.

  3. In Postman, change the custom authorization token header value to unauthorized and choose Send.

    
                            Call API with Custom Authorization Unauthorized Token

    The response shows that API Gateway returns a 401 Unauthorized response without authorizing the call to access the HTTP endpoint.

  4. Now, change the custom authorization token header value to fail. Choose Send.

    
                            Call API with Custom Authorization Fail Token

    The response shows that API Gateway returns a 500 Internal Server Error response without authorizing the call to access the HTTP endpoint.