Menu
Amazon API Gateway
Developer Guide

Use Amazon API Gateway Custom Authorizers

Amazon API Gateway Custom Authorizers

An Amazon API Gateway custom authorizer is a Lambda function that you provide to control access to your APIs using bearer token authentication strategies, such as OAuth or SAML.

When a client calls your API, API Gateway verifies whether a custom authorizer is configured for the API. If so, API Gateway calls the Lambda function, supplying the authorization token extracted from a specified request header. You use this Lambda function to implement various authorization strategies, such as JSON Web Token (JWT) verification and OAuth provider callout, to return IAM policies that authorize the request. If the returned policy is invalid or the permissions are denied, the API call will not succeed. For a valid policy, API Gateway caches the returned policy, associated with the incoming token and used 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.

API Gateway custom authorization workflow

Create the 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 authenticate and authorize 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. For illustration purposes, we will explain here the creation of the Lambda function without using the blueprint.

Note

The custom authorizer Lambda function presented here is for illustration purposes. 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 will be asked to assign an execution role for the Lambda function if it calls other AWS services. For the following example, the basic AWSLambdaRole will suffice. For more involved use cases, follow the instructions to grant permissions in an execution role for the Lambda function.

In the code editor of the Lambda console, enter the following Node.js code.

console.log('Loading function');

exports.handler =  (event, context, callback) => {
    var token = event.authorizationToken;
    // Call oauth provider, crack jwt token, etc.
    // In this example, the token is treated as the status for simplicity.

    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"); 
    }
};

var generatePolicy = function(principalId, effect, resource) {
    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;
    }
    
    // Can optionally return a context object of your choosing.
    authResponse.context = {};
    authResponse.context.stringKey = "stringval";
    authResponse.context.numberKey = 123;
    authResponse.context.booleanKey = true;
    return authResponse;
}

The preceding Lambda function returns an Allow IAM policy on a specified method if the request's authorization token contains an 'allow' value, thereby permitting a caller to invoke the specified method. The caller receives an 200 OK response. The function returns a Deny policy against the specified method if the authorization token has a 'deny' value, thus blocking the caller from calling the method. The client will receive a 403 Forbidden response. If the token is 'unauthorized', the client will receive a 401 Unauthorized response. If the token is 'fail' or anything else, the client will receive a 500 Internal Server Error response. In both of the last two cases, the calls will not succeed.

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.

Besides returning an IAM policy in a custom authorizer, the Lambda function must also return the caller's principal identifier and can optionally return a key-value map named context to contain additional information. For more information, see Output from an Amazon API Gateway Custom Authorizer.

You can then configure the integration request to pass returned context map entries to the back end. When the context map entries refer to cached credentials, the back-end service can provide better latency and, hence, improved custom experience by leveraging 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, the context object returned from an custom authorizer is passed to the back-end Lambda function as the input event. You can retrieve the context key-value pairs in the Lambda function by calling <codeL>$event.requestContext.authorizer.key</codeL>. For the preceding custom authorizer example, key can be stringKey, numberKey or booleanKey.

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 a Custom Authorizer and Output from an Amazon API Gateway Custom Authorizer.

Input to an Amazon API Gateway Custom Authorizer

When a custom authorizer is enabled on an API method, you must specify a custom header for the method caller to pass the required authorization token in the initial client request. Upon receiving the request, API Gateway extracts the token from the custom header as the input authorizationToken parameter value into the Lambda function and calls the custom authorizer with the following request payload.


{
    "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 payload type. Currently, the only valid value is the TOKEN literal. 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 custom authorizer shown in the preceeding 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 (*).


{
    "type":"TOKEN",
    "authorizationToken":"allow",
    "methodArn":"arn:aws:execute-api:us-west-2:123456789012:ymy8tbxw7b/*/GET/"
}            
        

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.


{
  "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": {
    "key": "value",
    "numKey": 1,
    "boolKey": 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.

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 back end. For more information, see Accessing the $context Variable.

You can access the key, numKey, or boolKey value (i.e., value, 1, or true) of the context map in a mapping template by calling $context.authorizer.key, $context.authorizer.numKey, or $context.authorizer.boolKey, respectively. Notice that a JSON object or array is not 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 (*).


{
  "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, you can configure the API Gateway Custom Authorizer in the API Gateway console.

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.

  3. Choose Create, select Custom Authorizer, and do the following:

    • In Lambda region, select the region where you upload your custom authorizer's Lambda function.

    • In Lambda function, select the Lambda function for your custom authorizer.

      Note

      You must first create a custom authorizer Lambda function in the region for it to be available in the drop-down list.

    • In Authorizer Name, enter a name for your new custom authorizer.

    • Leave Execution role blank to let the API Gateway console to set a resource-based policy to grant API Gateway permissions to invoke the authorizer Lambda function or 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.

    • In Identity token source, type the mapping expression for your authorizer's custom header.

      Note

      The custom header mapping expression is of the method.request.header.<name> format, where <name> is the name of a custom authorization header submitted as part of the client request. In the following example, this custom header name is Auth.

    • In Token validation expression, you can optionally provide a RegEx statement for API Gateway to validate the input token before calling the custom authorizer Lambda function. This helps you avoid or reduce the chances of being charged for processing invalid tokens.

    • In Result TTL in seconds, you can change or use the default (300) value to enable caching (>0) or disable caching (=0) of the policy returned from the Lambda function.

      Note

      The policy caching uses a cache key generated from the supplied token for the targeted API and custom authorizer in a specified stage. 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.

    Configure Method Request Custom Authorizer
  4. If you choose to let the API Gateway console to set the resource-based policy, the Add Permission to Lambda Function dialog will be 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.

This completes the procedure to create a custom authorization. The next procedure shows how to configure an API method to use the custom authorizer.

Configure an API Method to Use the 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 Authorization Settings, expand the Authorization drop-down list to select the custom authorizer you just created (myTestApiAuthorizer), and then choose the checkmark icon to save the choice.

    Configure Method Request Custom Authorizer
  4. Optionally, while still on the Method Request page, choose Add header if you also want to pass the custom authorization header to the back end. In Name, type a custom header name that matches the header mapping expression you used when you created the custom authorization, and then choose the checkmark icon to save the settings.

  5. Choose Deploy API to deploy the API to a stage. Make a note of the Invoke URL value. You will need it when calling the API.

Call an API Using API Gateway Custom Authorization

After you configure your API to use the custom authorizer, you or your customers can call the API using the custom authorizer. Because it involves submitting a custom authorization token header in the requests, you need a REST client that supports this. In the following examples, API calls are made using the Postman Chrome App.

Note

When calling an authorizer-enabled method, API Gateway will not log the call to CloudWatch if the required token is not set, null or invalidated by the specified Token validation expression.

Calling an API with Custom Authorization Tokens

  1. Open the Postman Chrome App, 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.