|
| 1 | +# Authorization checks |
| 2 | + |
| 3 | +The majority of operations, whether reads or writes, require authorization: |
| 4 | +permission to do the thing the user is asking to do. Additionally, it is |
| 5 | +important to be careful how much information is provided to _unauthorized_ |
| 6 | +users, since leaking information can be a security concern. |
| 7 | + |
| 8 | +## Guidance |
| 9 | + |
| 10 | +Services **must** check authorization before validating any request, to ensure |
| 11 | +both a secure API surface and a consistent user experience. An operation |
| 12 | +**may** require multiple permissions or preconditions in order to grant |
| 13 | +authorization. |
| 14 | + |
| 15 | +If a request can not pass the authorization check for any reason, the service |
| 16 | +**should** error with `403 Forbidden`, and the corresponding error message |
| 17 | +**should** look like: "Permission `{p}` denied on resource `{r}` (or it might |
| 18 | +not exist)." This avoids leaking resource existence. |
| 19 | + |
| 20 | +If it is not possible to determine authorization for a resource because the |
| 21 | +resource does not exist, the service **should** check authorization to read |
| 22 | +children on the parent resource, and return `404 Not Found` if the |
| 23 | +authorization check passes. |
| 24 | + |
| 25 | +### Multiple operations |
| 26 | + |
| 27 | +A service could encounter a situation where it has two different operations |
| 28 | +with two different permissions, either of which would reveal the existence of a |
| 29 | +resource if called, but a user only has permission to call one of them. |
| 30 | + |
| 31 | +In this situation, the service **should** still only check for authorization |
| 32 | +applicable to the operation being called, and **should not** try to "help out" |
| 33 | +by checking for related authorization that would provide permission to reveal |
| 34 | +existence, because such algorithms are complicated to implement correctly and |
| 35 | +prone to accidental leaks. |
| 36 | + |
| 37 | +For example, posit a scenario where: |
| 38 | + |
| 39 | +- A resource exists within a given collection that a user is unable to read. |
| 40 | +- The user _does_ have the ability to create other resources, and the |
| 41 | + collection uses user-specified IDs (meaning that a failure because of a |
| 42 | + duplicate ID would reveal existance). |
| 43 | + |
| 44 | +In this situation, the get or create methods **should** still only check |
| 45 | +_their_ permissions when determining what error to return, and not one |
| 46 | +another's. |
| 47 | + |
| 48 | +## Rationale |
| 49 | + |
| 50 | +[RFC 7231 §6.5.3][] states that services are permitted to use `404 Not Found` |
| 51 | +in lieu of `403 Forbidden` in situations where the service does not want to |
| 52 | +divulge existance, whereas this AIP argues for the use of `403 Forbidden` |
| 53 | +instead. We take this position for the following reasons: |
| 54 | + |
| 55 | +- The practice of "getting `404 Not Found` until you have enough permission to |
| 56 | + get `403 Forbidden`" is counter-intuitive and increases the difficulty of |
| 57 | + troubleshooting. |
| 58 | + - A service _could_ ameliorate this by sending information about missing |
| 59 | + permissions while still using the `404 Not Found` status code, but this |
| 60 | + constitutes a mixed message. |
| 61 | +- While `403 Forbidden` is essentially always an error requiring manual action, |
| 62 | + `404 Not Found` is often a valid response that the application can handle |
| 63 | + (e.g. "get or create"); overloading it for permission errors deprives |
| 64 | + applications of this benefit. |
| 65 | +- RFC 7231 §6.5.4 states that `404 Not Found` results are cacheable, but |
| 66 | + permission errors are not generally cacheable. Sending explicit cache |
| 67 | + controls on a conditional basis could ameliorate this, but would defeat the |
| 68 | + purpose. |
| 69 | +- The guidance here is more consistent with most other real-world authorization |
| 70 | + systems. |
| 71 | + |
| 72 | +[rfc 7231 §6.5.3]: https://tools.ietf.org/html/rfc7231#section-6.5.3 |
0 commit comments