Skip to main content

Enforce permissions at an API gateway or proxy

Understand the design choices for enforcing Permit.io permissions at an API gateway or reverse proxy, before you set up a specific integration. This page is for developers who add an authorization layer in front of their services, such as Kong, NGINX, or AWS API Gateway, in addition to or instead of permit.check() calls in application code.

A gateway or proxy acts as a policy enforcement point (PEP): it asks a policy decision point (PDP) whether the authenticated user can call the requested endpoint, then forwards or blocks the request. Gateway checks work at the endpoint level. Keep finer-grained checks, such as checks on a specific record, in your application code.

Gateway and proxy integrations

IntegrationHow the gateway asks the PDPWhat it takes to block a denied requestGuide
AWS API GatewayA Lambda authorizer calls the PDP with the Permit Python SDKThe authorizer returns a Deny policy, and API Gateway blocks the callAWS API Gateway
Kong GatewayThe Kong OPA plugin calls the PDP's /kong endpointA reverse proxy between Kong and the PDP, because the plugin can't send the PDP its API keyKong API Gateway
NGINXThe auth_request module sends a subrequest to the PDP's /nginx_allowed endpointAn njs or Lua handler, because /nginx_allowed returns HTTP 200 for a denied check and auth_request reads only the status codeNGINX
Other gateways or custom proxiesYour gateway calls the PDP HTTP APIYour gateway reads the allow field of the response and blocks the requestCall the PDP API directly

Model endpoints as resources and actions

Each HTTP endpoint and method is a small, well-defined operation, which makes it a natural unit for a gateway decision. In both modeling methods, URL mapping and endpoint resources, the PDP checks the permissions of the user who authenticated the request.

Map URLs to existing resources and actions

With URL mapping, you keep the resources and actions of your existing policy and add rules that map each HTTP method and URL to a resource and an action. One policy then serves both your application code and the gateway, and you don't create a policy entry for every endpoint.

For example, a document resource with a write action can map to both POST /blogs and POST /articles. URL mapping fits API gateways well, because gateway routes already list every endpoint in a structured form.

To set up mapping rules and send URL checks to the PDP, see Check permissions by URL with simple URL mapping.

Model each endpoint as a resource

With the second method, you create a dedicated policy for the gateway: the endpoint URL is the resource, and the HTTP method is the action. A policy that follows your endpoint naming convention gives you a rule per endpoint. The trade-off is that the gateway policy duplicates rules you may already have in the application policy.

Map the request to the decision request

Both methods use the same convention to turn an HTTP request into a decision request:

Request partDecision request field
URL or endpointResource
HTTP methodAction
Token of the authenticated userUser

The gateway maps these request parts to the fields the PDP expects. When a decision needs more detail than the URL, method, and user, such as an attribute read from the request, add a transformer to the gateway configuration. A transformer builds the decision request from the HTTP request, for all endpoints or for a subset of endpoints.

Choose a policy model for gateway checks

The policy model changes how much request data the gateway has to extract:

Policy modelGateway workTrade-off
Role-based access control (RBAC)Map the endpoint to a resource and use the user's rolesLeast work, but the decision can't depend on the specific object
Attribute-based access control (ABAC)Extract attributes from the request, such as fields in the bodyTransforming the request into attributes adds work to every request
Relationship-based access control (ReBAC)Extract the resource instance, such as an ID in the pathYou need a consistent way to read the instance from each request

Pick the simplest model that answers the question the gateway must decide, and keep object-level decisions in application code when the request doesn't carry enough data.

Manage the gateway policy as code

Most gateways and proxies are configured with infrastructure-as-code files. Declare the Permit policy for the gateway the same way, with the Permit Terraform provider, so gateway routes and the policy that protects them change in the same review and deployment.

The following Terraform resource declares a document resource whose actions use HTTP methods as keys:

resource "permitio_resource" "document" {
key = "document"
name = "document"
description = "documents endpoint"
actions = {
"GET" = {
"name" = "read"
}
"POST" = {
"name" = "write"
}
"PUT" = {
"name" = "update"
}
"DELETE" = {
"name" = "delete"
"description" = "delete a document"
}
}
attributes = {
"title" = {
"description" = "the title of the document"
"type" = "string"
}
}
}

Run the PDP next to the gateway

The gateway calls a PDP for every request it authorizes. Run an Edge PDP in the same network as the gateway or proxy, so authorization requests don't leave your network and each check avoids a round trip to an external service. You can run the PDP container with Docker or a Helm chart. See Deploy the PDP to production.

You can connect the gateway to the PDP in two ways:

  • Gateway plugin. The Permit PDP is built on Open Policy Agent (OPA), and it exposes an endpoint for the Kong OPA plugin at /kong. The Kong OPA plugin has no configuration field for the headers it sends, so it can't send the PDP the API key the PDP requires, and the setup needs a reverse proxy between Kong and the PDP that adds the header. See Authorize Kong Gateway requests with Permit.
  • PDP HTTP API. For a custom gateway or proxy, or when you prefer a direct call, send the decision request to the PDP API. See Call the PDP API directly.
PDP endpoints require the API key

The PDP answers an authorization request without an Authorization: Bearer <API key> header with HTTP 401. Configure the gateway, or a proxy in front of the PDP, to send your environment API key (Get your API key) on every request to the PDP. Without the header, every request the gateway tries to authorize fails.

Filter response data

A gateway check returns allow or deny for the whole request. Data filtering returns only the objects the user can access, for example when a GET endpoint returns a list of documents. You can filter data in two ways:

  • Filter with the Permit API. Call a data filtering method from the service behind the list endpoint, so the endpoint returns only allowed objects. This option works with your existing Permit policy. See Filter data by permission.
  • Partial evaluation with custom Rego. Write custom Rego with the GitOps feature, and use OPA partial evaluation to generate a filter query from the policy. This option takes more development and maintenance.

For help with partial evaluation, ask in the Permit Slack community.

Next steps