Evaluating access control methods to secure Amazon API Gateway APIs
This post is written by Bryant Bost, Cloud Application Architect.
There is not a one-size-fits-all approach to access control for Amazon API Gateway. Properties of your application such as API type, identity provider, client access patterns, privacy requirements, and others influence the design of your access control solution.
Understanding the types of access control available in API Gateway can help you design a solution that is right for your application. In this post, we review the different access control methods available in API Gateway, in addition to considerations for evaluating whether a method is right for your application.
Access control in API Gateway
Access control in API Gateway is made up of a combination of domains:
- Identity-based: control access to an API based on the authenticated identity of a user. For instance, a user can be granted access to an API based on their OAuth 2.0 access token or an assumed AWS Identity and Access Management (IAM) role.
- Resource-based: control access to an API based on IAM resource policies containing IAM statements that are assigned directly to API Gateway resources. See identity-based policies and resource-based policies for more information on resource policies and how IAM policies are evaluated.
- Network-based: control the network accessibility of your APIs.
The following table outlines access control methods available to each API type. Access control methods can be combined, but only one identity-based access control method can be associated with a specific endpoint. For instance, you cannot use both IAM permissions and a JSON Web Token (JWT) authorizer to access to the same endpoint.
|Access Control Method||Category||Description||HTTP APIs||REST APIs||WebSocket APIs|
|IAM permissions||Identity-based||Use IAM policy statements and Signature Version 4 (SigV4)||Yes||Yes||Yes|
|JWT authorizers||Identity-based||Automatically verify JWTs using OpenID Connect (OIDC) / OAuth 2.0||Yes||No||No|
|AWS Lambda authorizers||Identity-based||Implement custom logic in a Lambda function.||Yes||Yes||Yes|
|Amazon Cognito user pool authorizers||Identity-based||Automatically verify tokens that belong to an Amazon Cognito user pool.||No, but you can use a JWT authorizer with Amazon Cognito||Yes||No|
|Resource policies||Resource-based||Add IAM resource policies.||No||Yes||No|
|Private endpoints||Network-based||Create private endpoints that are only accessible through an interface VPC endpoint.||No||Yes||No|
|Mutual TLS (mTLS)||Network-based||Use client and server X.509 certificates.||Yes||Yes||No|
Access control methods available to each API type
IAM permissions can be used to control access to an API Gateway endpoint based on its Amazon Resource Name (ARN). In this model, an IAM policy defines allow or deny access to an endpoint, and this policy is attached to an IAM principal. IAM policy statements provide the authorization component, and the SigV4 signing process provides the authentication component. IAM-based access control is not feasible for client applications that are unable to integrate with IAM.
IAM permissions are a good fit for:
- Applications using Amazon Cognito identity pools: Amazon Cognito identity pools rely on identity federation to provide temporary AWS credentials to users. These credentials can be used to add SigV4 signatures to API requests.
- Resources already integrated with IAM: For resources that already have access to IAM credentials, adding IAM policy statements will allow API access without additional client-side changes.
A Lambda authorizer is responsible for both the authentication and authorization processes. When Lambda-based authorization is configured on an API, API Gateway invokes the Lambda authorizer and uses the caller’s identity as input. The output from the Lambda authorizer determines whether the caller can access the API.
The input, output, and implementation of a Lambda authorizer varies for each API type. The following diagram shows the high-level steps involved in using a Lambda authorizer to control access to an API.
- Request: User issues a request to API Gateway and includes their identity in the request. Identity can be established with a bearer token or with request parameters.
- Capture: API Gateway extracts identity and request information. This information is used as the input to the Lambda authorizer.
- Authorize: Lambda authorizer verifies the identity and runs custom authorization logic.
- Evaluate: API Gateway evaluates the output of a Lambda authorizer to determine if the request is allowed.
The following table details Lambda authorizers available to each API type.
|Lambda authorizer||API type||Description|
|Lambda authorizer 1.0||HTTP||Uses request and identity information to generate an IAM policy that defines access to an API.|
|Lambda authorizer 2.0||HTTP||Uses request and identity information to generate a Boolean value or IAM policy that defines access to an API.|
|Token-based Lambda authorizer||REST||Uses request information and a bearer token to generate an IAM policy that defines access to an API.|
|Request parameter-based Lambda authorizer||REST, WebSocket||Uses a combination of request parameters and context information to generate an IAM policy that defines access to an API.|
Types of Lambda authorizers
Lambda authorizers are a good fit for:
- Third-party identity providers: Applications that use a third-party identity provider with REST APIs can use Lambda authorizers to allow users to access APIs directly with third-party credentials. If you are using an OIDC or OAuth 2.0 identity provider and HTTP APIs, consider using a JWT authorizer to perform token validation and inspection automatically.
- Custom authorization requirements: Lambda authorizers can implement arbitrarily complex and customizable authorization logic.
- WebSocket APIs not using IAM permissions: WebSocket APIs only have two available forms of authorization: IAM permissions and Lambda authorizers.
JWT authorizers automatically validate and inspect JWTs from any OIDC or OAuth 2.0 identity provider. The following example shows a common use case of JWT authorizers. In this example, a JWT authorizer automatically validates and inspects a user’s access token for the scope example-token-scope to invoke the /example-resource endpoint.
As a best practice, you should require your application to use access tokens and add authorization scopes to your API routes. This ensures that only authorized users with the correct token scope are able to access an API. You can use an ID token with a JWT authorizer. However, it is not possible to implement fine-grained permissions based on token scopes with an ID token because ID tokens do not have scopes.
JWT authorizers are a good fit for:
- OIDC or OAuth 2.0 authorization with HTTP APIs: Applications using HTTP APIs that rely on OIDC or OAuth 2.0 identity providers should use JWT authorizers to add managed validation and inspection of JWTs.
Amazon Cognito user pool authorizers
Amazon Cognito user pool authorizers perform much of the same functionality as JWT authorizers, but are only compatible with Amazon Cognito user pools.
Using an Amazon Cognito user pool authorizer in your application is predicated on using an Amazon Cognito user pool to manage the users of your application. For this reason, an Amazon Cognito user pool authorizer is only feasible for applications using tokens dispensed from an Amazon Cognito user pool.
Amazon Cognito user pool authorizers are a good fit for:
- Applications using REST APIs and an Amazon Cognito user pool: Amazon Cognito user pool authorizers allow you to validate and inspect tokens automatically that were issued by an Amazon Cognito user pool.
A resource policy allows you to define additional restrictions based on arbitrary IAM policy statements attached directly to an API.
Resource policies are a good fit for:
- Applying uniform restrictions: Resource policies are ideal for defining restrictions on API endpoints that apply to all requests regardless of identity. For instance, a resource policy allows you to restrict access according to a specific AWS account, specific IAM principals, a specific source IP or CIDR block, or a specific VPC or VPC endpoint.
By default, API Gateway endpoints are reachable over the public internet. To prevent this, REST APIs support the creation of private endpoints to limit the network accessibility of your endpoints. Private endpoints are restricted to requests that pass through an interface to VPC endpoints. Additionally, the interface VPC endpoint should be configured with a “VPC endpoint policy.” This is an IAM resource-based policy and should be used to specify which private APIs can be called via the VPC endpoint.
Private endpoints are a good fit for:
- Non-public applications: Applications that do not expose public endpoints can use private endpoints.
API Gateway supports client/server authentication using mTLS. mTLS is an extension of the TLS protocol that requires both the client and server to verify each other using X.509 certificates before a connection is established.
Using mTLS requires each client to be provisioned with an X.509 certificate. Because of this, mTLS may not be practical for applications with large user bases.
mTLS is a good fit for:
- Business-to-business (B2B) or internal applications: Applications with a limited number of clients can use mTLS to add an additional layer of security.
- Internet of Things (IoT) devices: IoT devices provisioned with an X.509 certificate can use mTLS to communicate securely with API Gateway over public networks.
This post reviews the access control methods available in API Gateway and the types of applications that are best suited for each method. Your application requirements determine the access control methods necessary to secure your application. For instance, a public internet application may only require identity-based access control. A secure internal application may require identity, resource, and network-based access controls. Finally, an IoT application may rely entirely on mTLS.
In general, use access control methods that provide the most automation while meeting the requirements of your client applications. For example, if you are using HTTP APIs and an OAuth 2.0 identity provider, then a JWT authorizer provides a fully automated solution compared to a Lambda authorizer. Similarly, if you have resources that are already integrated with IAM, use IAM credentials to access APIs instead of configuring an additional identity provider.
For more on building and securing serverless applications go to serverlessland.com.