Amazon API Gateway
Developer Guide

Use API Gateway Lambda Authorizers

A Lambda authorizer (formerly known as a custom authorizer) is an API Gateway feature that uses a Lambda function to control access to your API.

A Lambda authorizer is useful if you want to implement a custom authorization scheme that uses a bearer token authentication strategy such as OAuth or SAML, or that uses request parameters to determine the caller's identity.

When a client makes a request to one of your API's methods, API Gateway calls your Lambda authorizer, which takes the caller's identity as input and returns an IAM policy as output.

There are two types of Lambda authorizers:

  • A token-based Lambda authorizer (also called a TOKEN authorizer) receives the caller's identity in a bearer token, such as a JSON Web Token (JWT) or an OAuth token.

  • A request parameter-based Lambda authorizer (also called a REQUEST authorizer) receives the caller's identity in a combination of headers, query string parameters, stageVariables, and $context variables.

It is possible to use an AWS Lambda function from an AWS account that is different from the one in which you created your Lambda authorizer function. For more information, see Configure a Cross-Account Lambda Authorizer.

If you're already using Amazon Cognito User Pools to manage your user accounts, or if you're considering doing so, you may want to consider using an Amazon Cognito user pool as the authorizer for your API, instead of a Lambda authorizer.

Note

For WebSocket APIs, only request parameter-based authorizers are supported.

Lambda Authorizer Auth Workflow

The following diagram illustrates the authorization workflow for Lambda authorizers.


                API Gateway Lambda authorization workflow

API Gateway Lambda authorization workflow

  1. The client calls a method on an API Gateway API method, passing a bearer token or request parameters.

  2. API Gateway checks whether a Lambda authorizer is configured for the method. If it is, API Gateway calls the Lambda function.

  3. The Lambda function authenticates the caller by means such as the following:

    • Calling out to an OAuth provider to get an OAuth access token.

    • Calling out to a SAML provider to get a SAML assertion.

    • Generating an IAM policy based on the request parameter values.

    • Retrieving credentials from a database.

  4. If the call succeeds, the Lambda function grants access by returning an output object containing at least an IAM policy and a principal identifier.

  5. API Gateway evaluates the policy.

    • If access is denied, API Gateway returns a suitable HTTP status code, such as 403 ACCESS_DENIED.

    • If access is allowed, API Gateway executes the method. If caching is enabled in the authorizer settings, API Gateway also caches the policy so that the Lambda authorizer function doesn't need to be invoked again.

Steps to Create an API Gateway Lambda Authorizer

To create a Lambda authorizer, you need to perform the following tasks:

  1. Create the Lambda authorizer function in the Lambda console as described in Create an API Gateway Lambda Authorizer Function in the Lambda Console. You can use one of the blueprint examples as a starting point and customize the input and output as desired.

  2. Configure the Lambda function as an API Gateway authorizer and configure an API method to require it, as described in Configure a Lambda Authorizer Using the API Gateway Console. Alternatively, if you need a cross-account Lambda authorizer, see Configure a Cross-Account Lambda Authorizer.

    Note

    It is also possible to configure an authorizer by using the AWS CLI or an AWS SDK. See Configure a Lambda Authorizer Using the AWS CLI or an AWS SDK.

  3. Test your authorizer by using Postman as described in Call an API with API Gateway Lambda Authorizers.

Create an API Gateway Lambda Authorizer Function in the Lambda Console

Before configuring a Lambda authorizer, you must first create the Lambda function that implements the logic to authorize and, if necessary, to authenticate the caller. The Lambda console provides a Python blueprint, which you can use by choosing Use a blueprint and choosing the api-gateway-authorizer-python blueprint. Otherwise, you'll want to use one of the blueprints in the awslabs GitHub repository as a starting point.

For the example Lambda authorizer functions in this section, which don't call other services, you can use the built-in AWSLambdaBasicExecutionRole. When creating the Lambda function for your own API Gateway Lambda authorizer, you'll need to assign an IAM execution role to the Lambda function if it calls other AWS services. To create the role, follow the instructions in AWS Lambda Execution Role.

EXAMPLE: Create a Token-Based Lambda Authorizer Function

To create a token-based Lambda authorizer function, enter the following Node.js 8.10 code in the Lambda console and test it in the API Gateway console as follows.

  1. In the Lambda console, choose Create function.

  2. Choose Author from scratch.

  3. Enter a name for the function.

  4. For Runtime, choose Node.js 8.10.

  5. Choose Create function.

  6. Copy/paste the following code into the code editor.

    // A simple token-based 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' or an empty // string, the authorizer function returns an HTTP 401 status code. For any other token value, // the authorizer returns an HTTP 500 status code. // Note that token values are case-sensitive. exports.handler = function(event, context, callback) { var token = event.authorizationToken; switch (token) { 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"); // Return a 500 Invalid token response } }; // 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; }
  7. Choose Save.

  8. In the API Gateway console, create a simple API if you don't already have one.

  9. Choose your API from the API list.

  10. Choose Authorizers.

  11. Choose Create New Authorizer.

  12. Enter a name for the authorizer.

  13. For Type, choose Lambda.

  14. For Lambda Function, choose the region where you created your Lambda authorizer function and choose the function name from the dropdown list.

  15. Leave Lambda Invoke Role blank.

  16. For Lambda Event Payload, choose Token.

  17. For Token Source, enter tokenHeader.

  18. Choose Test.

  19. For the tokenHeader value, enter allow.

  20. Choose Test.

In this example, when the API receives a method request, API Gateway passes the source token to this Lambda authorizer function in the event.authorizationToken attribute. The Lambda authorizer function reads the token and acts as follows:

  • If the token value is 'allow', the authorizer function returns a 200 OK HTTP response and an IAM policy that looks like the following, and the method request succeeds:

    { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": "Allow", "Resource": "arn:aws:execute-api:us-east-1:123456789012:ivdtdhp7b5/ESTestInvoke-stage/GET/" } ] }
  • If the token value is 'deny', the authorizer function returns a 403 Forbidden HTTP response and a Deny IAM policy that looks like the following, and the method request fails:

    { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": "Deny", "Resource": "arn:aws:execute-api:us-east-1:123456789012:ivdtdhp7b5/ESTestInvoke-stage/GET/" } ] }
  • If the token value is 'unauthorized' or an empty string, the authorizer function returns a 401 Unauthorized HTTP response, and the method call fails.

  • If the token is anything else, the client receives a 500 Invalid token response, and the method call fails.

Note

In production code, you may need to authenticate the user before granting authorization. If so, you can add authentication logic in the Lambda function as well by calling an authentication provider as directed in the documentation for that provider.

In addition to returning an IAM policy, the Lambda authorizer function must also return the caller's principal identifier. It can also optionally return a context object containing additional information that can be passed into the integration backend. For more information, see Output from an Amazon API Gateway Lambda Authorizer.

EXAMPLE: Create a Request-Based Lambda Authorizer Function

To create a request-based Lambda authorizer function, enter the following Node.js 8.10 code in the Lambda console and test it in the API Gateway console as follows.

  1. In the Lambda console, choose Create function.

  2. Choose Author from scratch.

  3. Enter a name for the function.

  4. For Runtime, choose Node.js 8.10.

  5. Choose Create function.

  6. Copy/paste the following code into the code editor.

    exports.handler = function(event, context, callback) { console.log('Received event:', JSON.stringify(event, null, 2)); // A simple request-based 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, and stage variable of StageVar1 all match // specified values of 'headerValue1', 'queryValue1', and 'stageValue1', // 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; // 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") { 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); }
  7. Choose Save.

  8. In the API Gateway console, create a simple API if you don't already have one.

  9. Choose your API from the API list.

  10. Choose Authorizers.

  11. Choose Create New Authorizer.

  12. Enter a name for the authorizer.

  13. For Type, choose Lambda.

  14. For Lambda Function, choose the region where you created your Lambda authorizer function and choose the function name from the dropdown list.

  15. Leave Lambda Invoke Role blank.

  16. For Lambda Event Payload, choose Request.

  17. Under Identity Sources, add a Header named HeaderAuth1, a Query String named QueryString1, and a Stage Variable named StageVar1.

  18. Choose Test.

  19. For HeaderAuth1, enter headerValue1. For QueryString1, enter queryValue1. For StageVar1, enter stageValue1.

  20. Choose Test.

In this example, the Lambda authorizer function checks the input parameters and acts as follows:

  • If all the required parameter values match the expected values, the authorizer function returns a 200 OK HTTP response and an IAM policy that looks like the following, and the method request succeeds:

    { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": "Allow", "Resource": "arn:aws:execute-api:us-east-1:123456789012:ivdtdhp7b5/ESTestInvoke-stage/GET/" } ] }
  • Otherwise, the the authorizer function returns a 401 Unauthorized HTTP response, and the method call fails.

Note

In production code, you may need to authenticate the user before granting authorization. If so, you can add authentication logic in the Lambda function as well by calling an authentication provider as directed in the documentation for that provider.

In addition to returning an IAM policy, the Lambda authorizer function must also return the caller's principal identifier. It can also optionally return a context object containing additional information that can be passed into the integration backend. For more information, see Output from an Amazon API Gateway Lambda Authorizer.