# Policy Routing proposal
October 27, 2024
## Framing
Some authorization platforms (PDPs) need to be able to route to a specific tenant, instance, or "namespace".
Examples include:
- fga.dev - Auth0's multi-tenant authorization platform. It requires routing to a tenant as well as a specific "store" within a tenant.
- Aserto SaaS - requires routing to a tenant, a policy instance, and a "policy root".
- Open Policy Agent - requires routing to a specific module (e.g. `<policy_root>.<module_name>.<decision_name>`).
- Other multi-tenant systems may require at least routing to a tenant
- OPA-based platforms, such as Topaz and Permit, may require routing to specific modules/paths within the module.
## Challenge
While these routing details tend to be implementation-specific, there are some commonalities, and the AuthZEN spec should have a point of view of how a PDP should expose them.
This problem is analogous to how a PDP indicates to a caller that it needs an access token for an authenticated authorization call: while the AuthZEN spec does not mandate a format for the access token, it recommends that the HTTP `Authorization` header is used to provide this information to the PDP.
## Options
There are at least four mechanisms that PDP vendors could choose from for routing. Ideally we choose the smallest number of options.
Of course, some PDPs (e.g. a PDP that is deployed as a sidecar) may not need ANY of them, so these must be optional.
1. **Hostname**: the tenant, and potentially any additional routing information, is represented through a unique hostname that the PEP uses as the PDP's endpoint. Example: `https://my-tenant.fga.dev/access/v1/evaluation`.
2. **URL Path**: the tenant, and potentially any additional routing information, is encoded in the URL path. Example: `https://fga.dev/my-tenant/my-store/access/v1/evaluation`.
3. **HTTP Headers**: the PDP expects additional routing information to be expressed through custom HTTP headers. Example: `https://fga.dev/access/v1/evaluation` with an HTTP header `FGA-Tenant-ID: <tenant-id>`
4. **Payload**: the `context` field within the `evaluation` call's payload contains routing information.
## Recommendations
### Hostname
Mechanism 1 is completely transparent from the point of view of the AuthZEN spec - nothing is stopping implementations from using this mechanism already (and in fact some may already be doing it). However, this brings up the question of how a PDP would communicate a tenant-specific endpoint to a PEP.
#### .well-known
In OAuth2 ([RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414)), an Authorization Server can advertise its `token` and `authorization` endpoints via a discovery document.
Adding this mechanism would allow a PDP to advertise the full URL of its various endpoints.
> Note: it's quite likely that we need this mechanism anyway, since a PDP may implement only the `evaluation` endpoint, or also the `evaluations` endpoint, and perhaps any of the upcoming `search` endpoints. So we need this anyway!
### URL path
PDPs that use URL path segments for routing could use the same exact discovery (.well-known) mechanism we mention above to advertise their tenant- and/or instance-specific URLs for the `evaluation` (etc) calls.
This implies that the discovery endpoint itself may need to be tenant- and instance-specific. Multi-tenant PDP's can let users know what the discovery endpoint is (and potentially also contain configuration for all of its endpoints - `evaluation`, etc).
### HTTP Headers
Some implementations may not be able to express all of their routing informations entirely encoded in the URLs of their PDPs. Those implementations may need additional configuration.
A common mechanism for accomplishing this are custom HTTP headers. Using this mechanism has the advantage that it does not permute the payload structure of AuthZEN.
Example:
```
POST /access/v1/evaluation HTTP/1.1
Host: pdp.mycompany.com
Authorization: Bearer <myoauthtoken>
X-FGA-Tenant-ID: 8f4ffb9a-b064-11eb-9f95-008dbb604591
X-FGA-Store-ID: bfe9eb29-ab87-4ca3-be83-a1d5d8305716
```
As mentioned for the other mechanisms, a PDP is free to employ custom HTTP headers without violating any of the precepts of the AuthZEN specification. However, we may want to specify the names of the headers, in order to increase commonality / interoperability between implementations.
For example, we could add something like this to the HTTPS binding:
> If additional routing information is required by the PDP to address a specific tenant or instance, custom HTTP headers MAY be used for this purpose. In this case, it is RECOMMENDED that the following header names are used:
> - `X_AUTHZEN_TENANT_ID`
> - `X_AUTHZEN_INSTANCE_ID`
### Payload
Since tenancy and instance-level routing have nothing to do with the semantics of the authorization request, the least attractive option is to put this information in the payload structure.
If we must do this, we can recommend use the `context` field in the request for these routing elements.
As in the case of HTTP headers, we could also define recommended names of fields in the `context` block:
> If additional routing information is required by the PDP to address a specific tenant or instance, fields in the `context` block MAY be used for this purpose. In this case, it is RECOMMENDED that the following context field names are used:
> - `context.tenant_id`
> - `context.instance_id`