AIP-211

Authorization checks

The majority of operations, whether reads or writes, require authorization: permission to do the thing the user is asking to do. Additionally, it is important to be careful how much information is provided to unauthorized users, since leaking information can be a security concern.

Guidance

Services must check authorization before validating any request, to ensure both a secure API surface and a consistent user experience. An operation may require multiple permissions or preconditions in order to grant authorization.

If a request can not pass the authorization check for any reason, the service must error with PERMISSION_DENIED, and the corresponding error message should look like: "Permission {p} denied on resource {r} (or it might not exist)." This avoids leaking resource existence.

Note: This guidance conflicts with the guidance in the HTTP specification, which argues for the use of 404 in cases where the user lacks permission to know whether or not a resource exists. This variance is because of real-world challenges: the practice of "getting NOT_FOUND until you have enough permission to get PERMISSION_DENIED" is counter-intuitive and increases the difficulty of troubleshooting. Additionally, the guidance here is more consistent with most other real-world authorization systems.

If it is not possible to determine authorization for a resource because the resource does not exist, the service should check authorization to read children on the parent resource, and return NOT_FOUND if the authorization check passes.

Multiple operations

A service could encounter a situation where it has two different operations with two different permissions, either of which would reveal the existence of a resource if called, but a user only has permission to call one of them.

In this situation, the service should still only check for authorization applicable to the operation being called, and should not try to "help out" by checking for related authorization that would provide permission to reveal existence, because such algorithms are complicated to implement correctly and prone to accidental leaks.

For example, posit a scenario where:

  • A resource exists within a given collection that a user is unable to read.
  • The user does have the ability to create other resources, and the collection uses user-specified IDs (meaning that a failure because of a duplicate ID would reveal existance).

In this situation, the get or create methods should still only check their permissions when determining what error to return, and not one another's.