views:

485

answers:

5

I'm currently building a web application (utilizing Zend Framework) and have gotten some of the basic HTTP status codes down, such as:

  • 404 on missing controller/action
  • 500 on server exception
  • 3xx returned by Apache

At the moment I have just implemented some basic ACL checking that the user is authorized to access a certain resource. It's implemented as a controller plugin, doing its thing on the routeShutdown event. It works like follows:

  1. Get the role of the user. If the user is not logged in, assign the role of 'guest'
  2. Check that the user's rule has access to the resource

    2.1. If the does not have access to the resource and is a guest, save the resource he was trying to access, and forward him to a login prompt. Once he has supplied his credentials, he is redirected back to the original resource (via a HTTP redirect status code)

    2.2. If the user is authenticated and the ACL denies him access to the resource, he is forwarded to the error controller, to an action I've called noPrivilegies.

  3. If the user does have access, let the request continue as usual.

Now, my questions:

  1. Can/should I use HTTP 401 for the 2.1 scenario? It's not like I want a WWW-Authenticate header field sent by the client. I just need him to login through my login-form. But I still think that the request wasn't a 200 OK, since he didn't get access to the requested resource.
  2. Can/should I use HTTP 401 for the 2.2 scenario? Same reason here, WWW-Authenticate won't help. Perhaps it's better to use HTTP 403 Forbidden?
  3. Do you recommend any other status codes for these two scenarios?
  4. What other status codes do you usually return from your application, and when are they applicable?
+1  A: 

Normally I don't ever use the status codes to report 'application' level authentication failures. That's generally reported via the app.

And it makes sense to do that; because they can access the 'page' from a 'http' sense; they just can't access your applications processing of that page, if that makes sense.

What I'm saying is generally you don't worry about the codes, or set them yourself at all, when returning data to the client. Leave it to the webserver and provide an 'abstracted' method of responding; i.e. the typical 'invalid username or password' page, etc.

Just my view, though.

Noon Silk
I have to say I disagree.. Say you run into a problem with your database. It makes no sence to have a 200 OK and still display "Oops, we seem to experience problems at the moment, blablablabla".
PatrikAkerstrand
but displaying "oops... blabla bla" is way better then display an 500 error.
Rufinus
@Machine: Well, it does, because the *page* loaded succesfully, (http 200), but there was an *application* level problem. Just because you don't have a database doesn't mean your app can't function; it more than likely can, in some way (i.e. report an error, provide alternatives, etc).
Noon Silk
@Silky: Again.. no. A page loaded correctly, not THE page that was requested. I'd display the error page giving a friendly message to the end-user, but I would also send the HTTP 500 server error status code, since the request wasn't completed successfully or as was intended.@Rufinus: of course they have to be combined. An error status code + friendly message for the end-user
PatrikAkerstrand
i would have thought that 50x (500 or 502) would be a correct response for an internal server error because then the client side can take then action differently from a 200 response.
Bob
If the user should only be given 200 (and, because they're handled by the browser, 301, 302, and 401), then why do the other codes exist?
kdgregory
Your view is very browser-centric and breaks down when the client is a piece of automated software. Using HTTP status codes on the response allows for much more reliable and effective automation, since the client is able to identify when problems occur instead of just getting a 200 OK and then having to examine the returned page for error messages (and hoping that the error messages haven't been changed into something that it won't recognize).
Dave Sherohman
@kdgregory joking right? the webserver uses all the codes.
Noon Silk
@machine please try understanding before flat-out disagreeing. yes, 500 error is okay to return.
Noon Silk
@silky Sorry if you feel offended. It wasn't my intention. I just feel that the application can/should return other codes than 200 OK when a request can not be fulfilled as the user could expect. I agree that it probably doesn't matter to a non-developer end-user, but that doesn't make it any less valuable to follow best practices. I agree full heartily with @Dave and his comment.
PatrikAkerstrand
@silky - not joking at all. Many of the status codes make sense only within the scope of a "web application" (broadly defined). For example, 302 says that something has moved temporarily, but that the client should continue to use the original URL because it might be valid in the future. The web-server by itself has absolutely no need to return that status code, it is only useful for an application that reacts to current state.
kdgregory
I agree with silky. IMHO if it is a web application and this (the controller) controlle the browser interaction then you should behave like @silky says. And other interactions (web services, ohter applications, etc.) should have another point of interaction with apropriate behavior.
Leonel Martins
Dave has a point. giving the proper errormessage in combination with an http status code seems not so bad at all. Regarding the "permission denied" i also would go with Dave's statement in his answer below.
Rufinus
@Others of you : So do you return HTTP 404 if a search on your webserver can't find data for a users search?
Noon Silk
No not at all, since the user then wants to be displayed the search results, and the search results might very well be empty. However, IF the search action required some permissions that the user does not have, so he isn't ALLOWED to make the search in the first place, then I would send another status code than 200 when displaying the "Permission denied" page instead of the search results page.
PatrikAkerstrand
What you're all referring to is a similar to a REST interface, which is fine, but it's not appropriate for a 'browser' interface.
Noon Silk
+1  A: 

i've recently implemented something that works in a similar way, we return a 401 response when a user has to login and a 403 if after login they've tried accessing something that they don't have permission to access.

you can also set the reason phrase in the http response to something to denote the reason for the failure.

Bob
+2  A: 

I think that 403 is the correct response. Per the HTTP spec, 401 is for cases where HTTP-level authentication is possible and required, 403 is for cases where the user does not have permission to access the resource. In the case of your app, the user has logged in, and it's unreasonable to expect that s/he will be able to use a different account.

kdgregory
+2  A: 
  1. Provided that the guest role may be allowed to perform some actions, then no 4xx response or other form of error is warranted at stage 2.1 of your process because not being logged in is not an error.

  2. Neither 401 nor 403 is really ideal for an application-level "permission denied", but weighing 401's "The response MUST include a WWW-Authenticate header field" against 403's "Authorization will not help", I would say (and most cases I've encountered to date seem to agree) that 401 is the appropriate response if you are requesting HTTP level authentication before proceeding and 403 is appropriate in all other cases. So probably 403 in your case.

Dave Sherohman
+1  A: 

Even not specifically stated in HTTP spec, the common practice is

401 - For authentication error 403 - For authorization error

Try not to use 401 if you don't want authenticate user. I recently encountered a problem with a HTTP client (not one of the popular browsers) that it logs an error when it sees 401 but not WWW-Authenticate header. Granted this is a bug on the client side but it shows how people perceives 401.

ZZ Coder