Search code examples
apiresthttp-status-codes

What HTTP Code response to use when checking user PIN?


I have endpoint POST /auth/check-pin with JSON body

{
  "subAccountId": 1,
  "pin": 5555
}

What responses should I return when subAccountId not exists or when PIN is wrong? 404 for not exists subAccount and 400 for bad PIN?


Solution

  • 404 for not exists subAccount

    No, that's certainly wrong.

    HTTP status codes are part of the transfer of documents over a network domain. They are a form of metadata that allows general purpose components to understand the semantics of the response.

    The HTTP definition of 404 is:

    The 404 (Not Found) status code indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists.

    The target resource is the thing identified by the uri in the request line. In your example, /auth/check-pin is the identifier for this request. The meaning of 404, in this context, is that we weren't able to find /auth/check-pin -- in other words, there appears to be a spelling error in the target-uri.

    That meaning isn't a particularly good fit for your case, because the problems in your request are in the request-body, not in the target-uri.

    More reasonable choices are 403 Forbidden, which roughly translates to "I understood what you want, but I'm not going to do it"; 409 Conflict "the current state of the resource doesn't allow us to do that", or 422 Unprocessable Entity.

    In practice - it doesn't matter much which of these you choose, because beyond the semantics there isn't a lot of standardized differences between them (for example, they all have the same implications for caches).


    A second thing to consider here is how much information you want to give away to an attacker that is trying to guess pin numbers.

    If you give me the ability to distinguish between an invalid account number and a valid account number, this greatly reduces the amount of money I need to spend to compromise a pin.

    So if you are in a context that is sensitive to that, then you will not want to discriminate at all between unrecognized subAccountId and unrecognized pin. So would use the same status code and the same response body for both cases, perhaps:

    403 Forbidden
    
    No more information available