REST-API, proper HTTP status code for invalid DELETE - api

I'm designing a RESTful API that is using the HTTP status codes and verbs as key components in communicating.
On the religious level it's on the zealot side of RESTafarian.
Rule of thumb for deciding HTTP status codes has been this graph, or similar resources.
GET /api/documents/1 - 401 User has not logged in
GET /api/documents/1 - 200 User has permission
GET /api/documents/1 - 403 User does not have permission
DELETE /api/documents/1 - 204 Users has permission
DELETE /api/documents/1 - 403 User does not have permission
GET /api/documents/2 - 404 Users permission irrelevant, resource does not exist
DELETE /api/documents/2 - 404 Users permission irrelevant, resource does not exist
DELETE /api/documents/1 - 404 Users has permission, resource already deleted
DELETE /api/documents/1 - 404 Users does not have permission, resource already deleted
Goals:
Consistency in usage
Not to expose private information through errors
Proper use of status codes for client or middle layer caches
Fail early, keep lookups to a minimum
In this situation there is a lot of different status code to chose from ( 404, 403, 410, 405) and in my case I went with 403 on a existing resource if its not yours to not clear the cache, and 404 on all non existing resources so to tell the clients to wipe that data.
But I do not like the switch from 403 to 404 on resources that are not yours.
I'm interested to hear from others how you solved this use-case, or in general what status codes you feel appropriate to send in all invalid DELETE calls, since I deem that as one of the hardest to be concise with.
(A lot of REST discussions and answers on the internet in it whole are just "Throw a 400 bad request, no one cares anyway", I do not have a problem that needs a quick fix or a pragmatic hack. Thanks)

General pointer: In case a resource exists but a user is not authorized to perform operations on it, you should return 401 over 403:
401 Unauthorized
Similar to 403 Forbidden, but specifically for use
when authentication is required and has failed or has not yet been
provided.
and
403 Forbidden
The request was a valid request, but the server is refusing to respond to it. Unlike a 401 Unauthorized response, authenticating will make no difference.
See also Correct HTTP status code when resource is available but not accessible because of permissions
I went with 403 on a existing resource if its not yours to not clear
the cache, and 404 on all non existing resources so to tell the
clients to wipe that data.
As pointed out earlier, 401 should be used instead of 403. 404 is ok to return if you just want to say "sorry, resource not found". If you however want to say "resource was here but it's not anymore and never again will be" (this appears to be the case in your situation) you can return 410:
410 Gone
Indicates that the resource requested is no longer available
and will not be available again. This should be used when a
resource has been intentionally removed and the resource should be
purged. Upon receiving a 410 status code, the client should not
request the resource again in the future. Clients such as search
engines should remove the resource from their indices
To summarize, this is how I would implement it in your case. The changes I made are in bold.
GET /api/documents/1 - 401 User has not logged in
GET /api/documents/1 - 200 User has permission
GET /api/documents/1 - 401 User does not have permission
DELETE /api/documents/1 - 204 User has permission
DELETE /api/documents/1 - 403 User does not have permission
GET /api/documents/2 - 404 Users permission irrelevant, resource does not exist
DELETE /api/documents/2 - 404 Users permission irrelevant, resource does not exist
DELETE /api/documents/1 - 410 User has permission, resource already deleted
DELETE /api/documents/1 - 401 User does not have permission, resource already deleted
For the last one, you can return 401 if you do not want the unauthorized user to know that there was a resource that has already been deleted. If you don't care you can return 410. That is for you to decide.
I do not like the switch from 403 to 404 on resources that are not yours.
It's perfectly fine to return different status codes depending on what the situation is.
I hope this helps you out a bit.

The response code for an invalid delete call depends on what the failure is. In your cases, I would go with:
DELETE /api/documents/1 - Users has permission
204 No Content
DELETE /api/documents/2 - Users permission irrelevant, resource does not exist
404 Not Found
DELETE /api/documents/1 - Users has permission, resource already deleted
410 Gone
DELETE /api/documents/1 - Users does not have permission, resource already deleted
403 Forbidden
The last call is the only one worth really talking about. I believe (and your graph agrees) that the user's lack of permission takes precedence over the resource already being deleted. If the user were to get a 410, then you'd be leaking information (resource already deleted).
As far as 401/403, 401 is "you haven't logged in yet". 403 is "you have logged in, and you don't have permission to do what you want". I don't see anything unusual in your usage of those codes.
Having said all this, I feel like I'm somehow misinterpreting the question.

I don't like the idea of a 404 as representing a failed delete where the resource cannot be found (or for a put or patch for that matter). It is fairly common to have DNS issues and for people to have parameter based routing issues that would both yield a 404 if the actual site could not be found. Introducing this type of ambiguity can make diagnosing simple problems really and unnecessarily difficult. I think 410 Gone is a better choice for representing a resource not found when it comes to APIs.

Related

Discord Bot error 403 forbidden change status

I have a bot, all the functionality works (Can send messages, read, issue roles). But if I want to change its own status (or read personal settings), then I immediately get an error 403 forbidden.

What HTTP status code return when user needs to be UNAUTHORIZED to access page

I was wondering what HTTP status code should I return if user that is authorized tries to access page that should be accessible only by unauthorized users.
Currently I am just throwing 404, but was wondering if there is some common approach for this.
HTTP Status Code 403 Forbidden can be used when a request isn't allowed based on the user's identification, so I guess it can be used in this case.
However, have you also considered sending back a Redirect (https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections) to send the user to a different resource that might be more appropriate because they are authenticated?
This is a common method used to redirect authenticated users away from login pages to their home screens or profile page.
Also, for future reference, I think you might be referring to autheNtication (with a N, the process of verifying a users identity) instead of authoriZation (with a Z, the process of determining whether an authenticated user has access to a particular resource)
https://www.okta.com/identity-101/authentication-vs-authorization/

REST API - request to another account's record returns empty string or HTTP 404?

Should be to the request to resource in REST API that belongs to another account returned HTTP 404 status code or HTTP 200 with an empty string?
You may be looking for 403 Forbidden. This is for a case when the resource is present, but the (possibly) logged in user does not have permission to get.
The 404 Not Found should only be used if the resource is not present, meaning other permissions would not help.
200 OK should only be given if the request completed successfully, the client got a valid representation of the resource.
Agree with #Robert Bräutigam that HTTP 403 seems most appropriate.
However, consider a URL like:
/api/some-user-user-id/profile
If you return 403 for existing users and 404 for non-existent users - you could be enabling outsiders to discover user ids.
This may or may not be a problem.

Valence will give 403 on a GET lp/courses to some student users

For some reason, some users who try to connect through my app receive a 403 response for the /courses end point of the valence API. See below for details:
The scenario:
User can authenticate with Desire2Learn and is permitted to hit the
/whoami end point. This is always the case as the API does not allow
for this end point to require permissions.
All routes are being retrieved by a GET request
Other routes I receive success responses include:
lp/news
lp/enrollments/myenrollments
le/dropbox/folders/
Once we try to hit lp/courses I receive a 403 forbidden.
I see this route is deprecated in 10.3.0, The D2L instance I am working with is on version 10.1.0
I'm wondering if this is a group permissions issue or if my authentication is incorrect (it does work for multiple other requests)? Any ideas will be appreciated.
It looks like the /courses endpoint did not have the right authentication for my user. IT turns out though that this was for good reason. Luckily I could use the information gathered in /myenrollments instead.

What HTTP error codes should my API return if a 3rd party API auth fails?

I'm writing a REST-ish API service the provides the ability to interact with the end user's data in other 3rd party services (themselves REST APIs) via OAuth. A common example might be publishing data from my service to a third-party service such as Facebook or Twitter.
Suppose, for example, I perform an OAuth dance with the end user and Facebook, resulting in some short-term access token that my service can use to interact with the user's Facebook account. If that access token expires and the user attempts to use my service to publish to Facebook, what sort of error do I return to the user?
401 doesn't seem quite right to me; it seems that 401 would apply to the user's auth state with MY service. 403 seems much more appropriate, but also quite generic.
401 is the way to go. Two excerpts from the RFC2616 which defines the HTTP protocol:
Section 10.4.2 (about 401):
If the request already included Authorization credentials, then the 401
response indicates that authorization has been refused for those
credentials.
This seems to be appropriate for expired tokens. There are authentication credentials, but they're refused, so the user agent must re-authenticate.
Section 10.4.4 (about 403):
The server understood the request, but is refusing to fulfill it.
Authorization will not help and the request SHOULD NOT be repeated.
This should be used when the resource can't be accessed despite the user credentials. Could be a website/API that works only on US being hit by a asian IP or a webpage that has been declared harmful and was deactivated (so the content WAS found, but the server is denying serving it).
On OAuth2, the recommended workflow depends on how the token is being passed. If passed by the Authorization header, the server may return a 401. When passed via query string parameter, the most appropriate response is a 400 Bad Request (unfortunately, the most generic one HTTP has). This is defined by section 5.2 of the OAuth2 spec https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-26
There's nothing wrong with being generic, and it sounds like a 403 status would be relevant - there is nothing stopping you from providing a more human readable version that elaborates in a bit more detail why.
I think the following is a comprehensive list if you have some level of ambition when it comes to error responses.
400 Bad Request
For requests that are malformed, for example if a parameter requires an int between 0-9 and 11 has been sent. You can return this, and in the response body specify parameter x requires a value between 0 and 9
401 Unauthorized
Used only for authorization issues. The signature may be wrong, the nonce may have been used before, the timestamp that was sent is not within an acceptable time window, again, use the response body to specify more exactly why you respond with this. For the sake of clarify use this only for OAuth related errors.
403 Forbidden
Expressly to signify that an operation that is well formed, and authorized, is not possible at all (either right now, or ever). Take for example if a resource has been locked for editing by another user: use the response body to say something along the lines of Another person is editing this right now, you'll have to wait mmkay?.
403 Forbidden can also have to do with trying to reach resources. Say for example that a user has access to a resource /resource/101212/properties.json but not to /resource/999/properties.json, then you can simply state: Forbidden due to access rights in the response body.
404 Not Found
The requested resource does not exist. Or the URL simply does not successfully map to an API in your service. Specify in response body.
405 Method Not Allowed
This is to represent that the API can not be called with for example GET but another method must be used. When this is returned also you MUST return the extra response header Allow: POST, PUT, etc.