What is the best HTTP status code error for failed password update? - rest

I'm building some REST API to be used in a native iOS/Android app.
One of the endpoints allows the user to update his password by providing 2 fields: old_password and password.
Which HTTP status code should I in the situation where the old_password is incorrect?
My first thought was a 401 error but I already use it when the authentication token is invalid and it automatically triggers a logout in the app.
400 doesn't seem to fit because the request is actually semantically correct, it is a specific authentication error. Maybe 422?

One thing to keep in mind is that status codes, like response headers, are metadata; they are there so that generic components that know nothing about the details of your API can participate intelligently -- for example, by invalidating caches, or throwing up dialogs to collect authentication credentials.
400 doesn't seem to fit because the request is actually semantically correct
In practice, 400 is usually fine; clients are supposed to treat an unrecognized 4xx class status code as they would treat 400. Put another way, you can use 400 unless you specifically want to induce a different behavior by the generic components.
For your specific case, 409 Conflict is probably the closest match
The 409 (Conflict) status code indicates that the request could not be completed due to a conflict with the current state of the target resource. This code is used in situations where the user might be able to resolve the conflict and resubmit the request. The server SHOULD generate a payload that includes enough information for a user to recognize the source of the conflict.
RFC 5789 suggests a distinction between 409 and 422 that may be interesting. Paraphrasing this distinction
422: This might include attempts to modify a resource in a way that would cause the resource to become invalid
409: the request cannot be applied given the state of the resource.
You can also make a reasonable argument that the entire 4xx class of response codes is inappropriate. For example, if the request method is POST, then the server is expected to
process the representation enclosed in the request according to the resource's own specific semantics
Which it did; successfully, even. It just didn't produce the most commonly expected successful result.
On the other hand, the JSON Patch would argue the other direction; your attempt to change the password would probably look something like
[
{ "op": "test", "path": "/password", "value": "old_password" },
{ "op": "replace", "path": "/password", "value": "new_password" }
]
If you provided the wrong password in the test, then that operation would be considered unsuccessful, which would in turn mean that the PATCH is unsuccessful. That in turn would invoke the arguments for error handling as described in HTTP Patch.

Related

HTTP status code for PATCH requests meaning "you are not allowed to make such request"

I am trying to implement some PATCH requests in our software(following https://www.rfc-editor.org/rfc/rfc7396). The resources have some fields which must not be modified, so I am thinking to return some error status code when such fields appear in HTTP JSON request body. 400 seems a bit too generic (I am using it for validation errors e.g. email format and the like). Perhaps there is some other status code used in such situations?
There's a code for that . . . 8-)
403 Forbidden
The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason
https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
Furthermore, 403 is suitable even if there are no credential problems.
This is explained in RFC7231 Section 6.5.3:
a request might be forbidden for reasons
unrelated to the credentials
RFC 7231 section 8.2 a status code registry, so that's the place to start.
This is clearly a problem with the request; something the client might be able to fix, so an entry from the 4xx class is appropriate.
405 Method Not Allowed is wrong for the case you describe -- a different merge patch document would be accepted by this resource, but not the one that is present.
403 Forbidden is wrong, as it communicates a problem related to credentials, but you are describing a problem with payload.
409 Conflict could be reasonable...
the request could not be completed due to a conflict with the current state of the target resource.
I don't see any reason that the conflict can't be in an immutable part of the "current state".
But I think your best bet is 422 Unprocessable Entity
The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity (hence a 415(Unsupported Media Type) status code is inappropriate), and the syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate) but was unable to process the contained instructions. For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.
Another good resource to consider is the HTTP Patch specification. RFC 5789 enumerates a number of reasons that a patch might fail, and what code would be appropriate to use in each context. You can decide for yourself whether you think those distinctions are appropriate in your circumstances.
There may also be more specific errors like "Conflicting State" that could be signaled with this status code, but the more specific error would generally be more helpful.

RESTful name for the method that does two operations

In the API I have tickets resource and there are 2 methods:
1) Get the ticket status (ticket can be locked/unlocked)
GET /api/tickets/:id
2) Update the ticket status
PUT /api/tickets/:id with status=locked|unlocked
What I need - is to combine the status check with the actual update in one API call. And I also need to know if the status was changed with the API call or it was already set to needed value. E.g:
ticket_status = "unlocked"
PUT /api/tickets/:id/check_lock
changes ticket_status to "locked" and responses with "success"
ticket_status = "locked"
PUT /api/tickets/:id/check_lock
ticket_status is already "locked" so we response with "ignored"
For reverse operation we can have
PUT /api/tickets/:id/check_unlock
I understand that we are breaking the single responsibility principle here by combining to operations but this is done to decrease number of API requests and this is going to be called very frequently.
So I'm looking for good names instead of those ugly "check_lock", "check_unlock" as they seem to be rather ambiguous.
Using something like
PUT /api/tickets/:id/check_lock
to update the lock status is not recommended (as not to say bad practice).
When reading check_something one usually thinks of a method that is safe i.e. one does not expect it to modify any value.
Your example PUT is not idempotent. i.e. invoking PUT two times on the same resource results in different outcomes. Which contradicts the HTTP Specification for PUT
PUT request is defined as replacing the state of the target
resource.
In your case it's best to use PATCH to update part ticket resource as described in RFC5789 or even https://www.rfc-editor.org/rfc/rfc6902
PATCH /api/tickets/:id/ HTTP/1.1
Host: example.org
Content-Type: application/json-patch+json
{ "op": "replace", "path": "/lock", "value": "unlock" }
You may choose to an ETag in your response to signal whether the resource has been modified or not.
Or just the HTTP Status Code 200 with a message body in which you return whether the resource was modified or not and also the new value of the lock state.
If you want to toggle the lock status you should use something like which is called "action resource". In this case use POST.
POST /api/tickets/:id/toggle_lock
As result you can return the new lock status and whether it was updated or not as part of the body of the HTTP 200 Status Code.
Thinking in resources I would not have a operation check_unlock.
I would suggest: GET /api/tickets/:id with the status of the ticket in the json answer. Even if you have two http calls.
Or if the status results in an error, you can answer with an error 400 or something like that.
I would take a slightly different approach and use the 409 Conflict status code.
The request could not be completed due to a conflict with the current
state of the resource. This code is only allowed in situations where
it is expected that the user might be able to resolve the conflict and
resubmit the request.
Successful session :
PUT /api/tickets/123 { ... locked: true ... }
200 OK
Already locked session :
PUT /api/tickets/123 { ... locked: true ... }
409 Conflict
POST /api/ticket-queue { // ticket data here }
201 Created

REST API & HTTP Status Code

I have a bunch of PUT operations which execute actions on the input resource.
Let's make an example: I have a payment operation in my API which state that a credit card must be charged by a specific Amount.
In my code I first verify if there is sufficient credit on the card and then execute the operation. If there is'nt sufficient amount I simply return 400 but I am not sure it is correct.
Which is the correct HTTP Status Code in cases like this?
I can, of course send a response with HTTP 200 and attach a payload with further details explaining the error. I can also send back an HTTP 400 Bad Request or even better an HTTP 412 Precondition Failed.
Which is the correct code to send in the response in scenario like this where the validation failed? Is there any resource that I can read to understand the rationale behind HTTP Status Codes and HTTP Verbs?
Use 422 Unprocessable Entity.
The 422 status code means the server understands the content type of the request entity (hence a 415 Unsupported Media Type status code is inappropriate), and the syntax of the request entity is correct (thus a 400 Bad Request status code is inappropriate) but was unable to process the contained instructions.
Failing that, simply use 400 for any error having to do with your business domain. As of June 2004, the description for error 400 was amended to read:
The server cannot or will not process the request due to something that is perceived to be a client error
If the operation failed because of data sent by the user (it seems to be the case), you should use status codes 400 (general) or 422 (more precise but coming from the WebDAV spec). You can return back additional hints about the error within the payload (the structure is up to you) like:
{
error: {
"field": "amount",
"message": "The amount isn't correct - Sufficient credit."
}
}
I think that code 412 doesn't apply here since it must be returned when your server doesn't meet a condition specified by the client (see headers If-* like If-Match, If-Modified-Since, ...).
Hope it helps you,
Thierry
IMO: I would stick with 200 and then parse out the response and deal with that. HTTP status codes are protocol status code, not something that you should use for dealing with application logic.
{
"error": {
"field": "amount",
"message": "The amount isn't correct - Sufficient credit."
}
}
In case of the above code, the service call worked fine warranting a return code 200. However, you application logic now needs to deal with the error reported.
If we are using a HTTP status code to indicate error, we will start to get flagged in our logs etc. even though there was no technical error.

REST design - An operation with multiple possible non-success payloads

I'm trying to design a REST method for an 'Add person' operation that has a bunch of business rules. There are multiple possible non-success payloads (for the business purposes), requiring defined structure (to allow the consumer to parse the detail).
For 'Add a person', one of the following non-successes could happen:
We believe the system already has person.
Payload: The ID of that person
There are some possible matches.
Payload: A list of possible duplicates, and an override code to submit the record 'for sure'
General validation errors
Payload: Array of 'Error' object. (Standard across the API)
Question - Response object
If they're all to return under a single HTTP error status code, would it be right to have a varied object like:
OverrideCode (for (1))
PersonPossibleMatches [] (also for (1))
PersonDuplicateId (for (2))
ErrorList [] (for (3))
And have the consumer + documentation explain the interpretation?
Question - Response code
Is 400 (Bad Request) the correct (or correct enough) HTTP status code for this? We use it largely for the field validation (also scenario (3) - just wondering if business rule / 'intermediate state' things like this are any different.
Are there a more appropriate codes to spread the 3x scenarios over? And is it ok for the payloads to be different?
Thanks.
There are two aspects you need to consider
HTTP response code.
Error response payload.
Point number 1 is relatively simple. You have 400 error code for bad requests. And 409 for conflicting resources. So far simple.
Now let us consider your scenarios:
We believe the system already has person.
Payload: The ID of that person
Design suggestion: you can send a response like below
Response code: 409
{
"error_code": "resource_exists",
"error_description": "Resource person with ID XXX already exists"
"debug_info": "",
"link" : [
{
"href": "http://host-name/persons/123456",
"rel": "person"
}
]
}
2. There are some possible matches.
Payload: A list of possible duplicates, and an override code to submit the record 'for sure'
Design suggestion:
In this case - you may want to use PUT to override the resource. No need to use special code.
Response Code: 400
{
"error_code": "potential_duplicates",
"error_description": "Potentially the resource is duplicate of one of the following. Please use PUT with the resource ID to update"
"debug_info": "",
"link" : [
{
"href": "http://host-name/persons/234",
"rel": "person"
},
{
"href": "http://host-name/persons/456",
"rel": "person"
},
{
"href": "http://host-name/persons/789",
"rel": "person"
}
]
}
General validation errors
Payload: Array of 'Error' object. (Standard across the API)
Design suggestion: Here you can simply use 400 response code and a meaningful response like the examples above.
This depends in part on how the operation is performed. Since you said the operation has a bunch of business rules, and the system returns a payload with an ID when the person already exists, let's assume the operation is non-idempotent due to unrelated side-effects, performed with a POST to a factory endpoint.
1. We believe the system already has person.
This is a no-brainer. As suggested by others, you should use a 409 Conflict status code, with a body describing the nature of the conflict. In this case, it seems like there's nothing else the user needs to do, and he can move forward to the next step in the workflow. If there's something he can do, it should follow a procedure similar to the next case.
2. There are some possible matches.
Assuming that the clients don't have any key to unambiguously identify a person, which seems to be your case since you're considering possible matches, here you should also use a 409 Conflict status code, with a body describing the nature of the conflict, but with instructions on how to solve it.
Some other answer suggests you to allow an overwrite parameter that could be used any time, other suggests using a PUT, but I disagree with that since there's nothing preventing a client from using the overwrite all the time, or skipping the POST and use the PUT to replace an existent close-match. Also, you may have concurrent clients trying to add or change a person that match each other, or a common existent group, which will lead to an ABA conflict.
The conflict resolution body should return a valid tag for each possible match, and the client should be instructed to resubmit the same request with the If-Match header and the collection of tags. It may be a single tag, as long as it's generated from key data from each member in the collection. This will enforce that the user first must try the request without any override. If there's a conflict the user is forced to specify the exact entities that will be overwritten, and you're protected from inconsistent updates in case someone changes the current state between the first and the second request.
If the tags don't match in the second request, meaning the state was changed by something else between them, you should fail with a 412 Precondition Failed error.
3. General validation errors
This is also a no-brainer. A 400 Bad Request detailing the error, which seems to be standard across your API.
You could use 409 for the duplicate entry - and arguably for the possible duplicate entries with the extra info in the payload.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.10
A 400 for validation errors would be the expected response.
It is a judgement call at the end of the day and it depends what would be easier for your rest clients and what they are doing.
Here's the design process I use when creating RESTful API responses for error cases:
Design the response payload for the error condition. Regardless of the error code that's used, it is always good practice to return some content within error responses so that clients can learn more about the error and how to avoid it in the future.
If there is an HTTP status code that accurately describes this error already, and it's not already in use for another error case, use that.
If the closest matching error code is already being used for another error case, it's still OK to use that code, but the response payload becomes the place where the different error cases under that code get distinguished from each other. Your documentation should clearly state that inspecting this code wouldn't be enough, and that clients should then also look into the response to see exactly what happened.
If none of the above are applicable, use the closest error code that's appropriate. Just as in #3, the documentation of your response payloads makes this approach possible. If it's an error that the client influenced, make it a 400-range error, probably 400 - Bad Request. If it's the server's fault, then it should be a 500-range error, probably 500 - Internal Server Error.
Please, please, never throw 200 - OK for errors. The world left that nonsense behind in SOAP land, and nobody wants to go back.
Now let's apply that thinking to your error cases:
We believe the system already has that person. As correctly stated in another answer, 409 - Conflict accurately describes that error, so you should just use that. Putting some descriptive error information in the response payload would help new users of your API, even with such a definitive and understandable code.
There are some possible matches. There really isn't an HTTP code that describes this, and it's something that the client could influence, so the closest would be the catch-all code of 400 - Bad Request. Including the list of possible duplicates is an interesting idea, but make sure you don't end up returning enormous responses with huge numbers of possible matches. Also, make sure to also return URIs to those matching resources so that your clients can easily consume them. As for the "override code" suggestion, I wouldn't return that in the payload. Rather, I'd just document a parameter to your "Add a Person" operation that would allow for overrides to occur at any time, not just after a failed first attempt. For example: POST /people?overwrite=true.
General validation errors This is definitely a job for 400 - Bad Request, along with a descriptive error payload. It sounds like you're already allowing an array of errors to be returned from any API call, so that should be good enough to capture all the validation failures for the client-supplied data.
How about explaining it with a payload back; That is how we deal with REST responses for clients.
Response HTTP 409 with following payload response indicating to client what should they do next
`
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<request-result>
<http-code>200</http-code>
<description>REST Request is successfully processed</description>
<internal-error-info>Person already Exists</internal-error-info>
<message>Person with <id> already exists in sytem. Try picking different ID/Name combination</message>
<requested-operation>Add a Person</requested-operation>
<resource-name>Person</resource-name>
<status>SUCCESSFUL</status>
</request-result>
`

HTTP status code in REST API for using GET to query a “Not Ready Yet, Try Again Later” resource?

First of all, I've read some relevant posts:
Best HTTP status code in REST API for “Not Ready Yet, Try Again Later”? It is about GET an item
Is it wrong to return 202 “Accepted” in response to HTTP GET? It is about GET an item
HTTP Status Code for Resource not yet available It is about POST
HTTP status code for in progress? It is about GET but no clear answer.
but I still think I should raise my question and my thoughts here. What should be the HTTP status code in REST API for using GET to QUERY a “Not Ready Yet, Try Again Later” resource? For example, client tries to query all local news happen in future(!) by make an HTTP GET to this url: http://example.com/news?city=chicago&date=2099-12-31 so what shall the server reply?
These are the http status code I considered, their rfc definition and why I am not fully satisfied with:
3xx Redirection. Comment: Not an option because there is no other link to be redirected to.
503 Service Unavailable: The server is currently unable to handle the request due to a temporary overloading or maintenance of the server. The implication is that this is a temporary condition which will be alleviated after some delay. If known, the length of the delay MAY be indicated in a Retry-After header. Comment: The retry behavior is desired, but semantically the situation is not server's fault at all, so all 5xx look weird.
4xx Client Error. Comment: Looks promising. See below.
413 Request Entity Too Large: The server is refusing to process a request because the request entity is larger than the server is willing or able to process. ... If the condition is temporary, the server SHOULD include a Retry- After header field to indicate that it is temporary and after what time the client MAY try again. Comment: The retry behavior is desired, however the "Entity Too Large" part is somewhat misleading.
417 Expectation Failed: The expectation given in an Expect request-header field (see section 14.20) could not be met by this server. Comment: So it should be caused by an Expect request-header, not applicable to my case.
406 Not Acceptable: The resource ... not acceptable according to the accept headers sent in the request. Comment: so it is caused by the Accept request-header, not applicable to my case.
409 Conflict: The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request. ... Conflicts are most likely to occur in response to a PUT request. Comment: This one is close. Although my case is not about PUT, and isn't actually caused by conflict.
404 Not Found: The server has not found anything matching the Request-URI. Comment: Technically, my url path (http://example.com/news) DOES exist, it is the parameters causing problems. In this case, returning an empty collection instead of a 404, is probably more appropriate.
403 Forbidden: The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. Comment: Generally this is supposed to be used in any restricted resource?
400 Bad Request: The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications. Comment: It is not true in my case. My server understands the request, its syntax is good, only the meaning is bad.
2xx Successful. Comment: If 4xx doesn't work, how about 2xx? See below.
200 OK. Comment: Fine. So what should I include in the response body? null or [] or {} or {"date": "2099-12-31", "content_list": null} or ... which one is more intuitive? On the other hand, I prefer a way to clearly differentiate the minor "future news" error from the more common "all query criteria are good, just no news this day" situation.
202 Accepted: The request has been accepted for processing, but the processing has not been completed. The request might or might not eventually be acted upon. Comment: Providing that we can use 202 in a GET request, it is acceptable. Then refer to the 200 comment.
204 No Content: The server has fulfilled the request but does not need to return an entity-body. Comment: Providing that we can use 204 in a GET request, it is acceptable. Just don't know whether this is better than 202 or 200.
More on 2xx: Comment: I assume all 2xx response will likely be cached somewhere. But in my case, if I return an empty body for "tomorrow's news", I don't want it to be cached. Ok, explicitly specify the "no cache" headers should help.
Your thoughts?
Use 404.
Your objection to it is based on a popular understanding of a URI as not including the querystring. "Because I have multiple URI's that map to the same handler," goes the logic, "my resource does in fact exist and is just being parameterized by querystring args."
This is incorrect. As the URI spec itself says in Section 3.3 (emphasis mine),
"The path component contains data, usually organized in hierarchical
form, that, along with data in the non-hierarchical query
component (Section 3.4), serves to identify a resource within the
scope of the URI's scheme and naming authority (if any)."
Resources are identified by URI's, and any change to any part of an absolute-URI identifies a separate resource. Tweet that to everyone you know once a day until they tell you to stop. Therefore a 404 is a perfect match: "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."
You are retrieving the news for that day, which is a valid day, there just isn't any news. A 200 response of an empty body, or a what ever makes sense based on the mediatype would seem the logical. This depends on the media type you have decided with the client.
404 would make more sense if the date format was wrong (you asked for the 45th day of November, or asked for a city that doesn't exist.)
As an aside the URL would be better in the format http://example.com/news/chicago/2099-12-31 since that is the specific resource you want to retrieve. This format would make things like 404s clearer as well.