1

I wanted to know what fellow developers follow while designing rest API error responses.

For all the not-found get resources, do you also send the some sort of body indicating that resource was not found or some more detailed level error messages or only error code with null or blank response?

  • What would you put in the body? – Robert Harvey Jan 2 at 19:56
  • Exactly, that was my thought as well. Some fellow devs in my organization send custom json like { "code": 404, "details": "Customer not found" } which I think does not make sense. – Ashish Jan 2 at 20:07
  • Unless that information makes it onto the UI or into a log somewhere, I don't think it adds any value. – Robert Harvey Jan 2 at 20:11
  • If I try to get information about a customer, and I get a 404, in which way would be "details": "Customer not found" be helpful to me? I know already that the customer was not found. – gnasher729 Jan 2 at 22:48
  • An example of it being done and another example making it a necessity: developers.google.com/drive/api/v3/handle-errors services.expediapartnercentral.com/products/documentation/api/… – user313675 Jan 2 at 23:09
9

For all the not-found get resources, do you also send the some sort of body indicating that resource was not found or some more detailed level error messages or only error code with null or blank response?

Safety first!

The first thing to consider is: can an attacker use that information for anything, including crafting better attacks in the future?

I often tell the cautionary tale of an exception in a pre-release version of .NET where the exception error message was basically "You don't have permission to know the name of directory C:\foo". That's a very helpful error message, but it defeats the purpose of hiding the secret from low-trust code. (This problem was caught and fixed before any version of .NET shipped to customers.)

In particular be careful of error messages that distinguish between "that doesn't exist" and "that exists but you can't see it". It is often a good idea to simply never return a 403 "forbidden" error and instead always return 404 "not found".

If your diagnostics allow an attacker to distinguish between forbidden and not found, they can use that difference to gradually enumerate the space of possibly-existing resources to determine which do and do not exist.

I introduced exactly this vulnerability into VBScript in the 1990s; an attacker could write a web page that gradually learned your machine's directory structure by checking error messages that made this distinction. They could not read files, but they could determine the names of files and directories by trial and error.

Thus, a good practice for web-based APIs is to fail to the secure mode: say as little as possible in an error message unless you know the client to be authenticated and trusted to have all the information in the error message.

  • In case of a hypothetical REST API I would assume some sort of authentication is in place – user313675 Jan 2 at 21:15
  • REST doesn't need to be authenticated. In fact, authenticated REST is a special beast because you have to do special authentication that maintains RESTfulness. That is a completely separate problem, but we should always code the error to default to the lowest security, then do special processing for authenticated errors. – Nelson Jan 3 at 7:20
  • @Nelson, not sure what you are trying to say, but if a client is not authenticated / authorized you always tell them they are not authenticated / authorized giving no other information, like a 404. – gnasher729 Jan 3 at 10:34
  • So basically never ever send a response body alongside with 4xx or 5xx errors. A non-sense. Sorry but I disagree with this reasoning. It just takes me a 1 valid URI to guess whether the URI+1 i'm testing "does not exist" or if it's resources "is not found". And a valid authorization of course. – Laiv Jan 3 at 13:01
  • @Laiv: Think bigger than just checking URLs. For example: suppose I want to find out if a user with email foo@bar.com has an account on a service, because I believe that this user can be phished. I send that user id and a blank password to the service. If I get a different error message for "no such user" and "wrong password" then I can know whether that user is a good phishing target for that service. Or, given a corpus of a few million known email addresses, I can gradually enumerate which of them are members of the service. – Eric Lippert Jan 3 at 18:34
4

It is very common for 404 responses to contain content in the body. The first example would be when you go to web sites, you get a helpful HTML page that has links to go back or go to the front page.

There is no reason why an API call shouldn't return a response body. In fact, it's something that the JSON:API specification encourages. The main reason is that it simplifies the error handling code on the client side if your server always returns content.

On the other hand, if you are not using the JSON:API standard, then you can make your own informed decision on the matter. The HTTP Status code does provide sufficient information for the client to know the resource does not exist. The only downside is that error handling in the client may be slightly more complex.

The only return HTTP status codes I am aware of that explicitly say should not have content include your 3XX codes for redirects and the 204 No Content code.

Bottom Line

As Eric Lippert cautions, if you return a body, make sure that the error message you provide does not share information that the user is not authorized to know. A 404 indicates that there is no resource by that URL.

I work with systems where every call to the core APIs are authenticated, so I know who is making the call, and I am assured of what permissions they have. That said, I do prefer to have a body that includes a generic error message saying the resource they were looking for could not be found.

3

The 4xx (Client Error) class of status code indicates that the client seems to have erred. Except when responding to a HEAD request, the server SHOULD send a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition.

404 is, of course, a status code of the 4xx class, therefore the body of the request should (in the RFC 2119 sense) include a message body.

Because the response includes a 4xx status code, general purpose components will know (a) that the included representation is that of an error, and not the resource itself (b) will know whether or not the error representation is cacheable (in the case of 404, by default the representation may be cached).

RFC 7807 describes application/problem+json, a media type designed for general purpose communication of errors.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.