47

I'm writing a small application which exposes a simple REST-ish HTTP API. I'm stuck trying to decide how to signal a failure due to a lack of authorization.

The app does not have an API for authentication, but instead depends upon the presence of a cookie containing a session token obtained by the client via another service. The app verifies the session and uses the identity obtained through the verification process to perform app-specific authorization. There is no way for a client to authenticate directly to this app.

My problem is that the obvious HTTP status code for rejecting unauthorized requests, "401 Unauthorized", is specified in terms of the "WWW-Authenticate" header. See rfc2616 sec 10.4.2.

The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource.

I can't believe this is an uncommon problem. Is it common to simply overload 401 to include more general uses? What about browsers popping up auth/e dialogs (which incidentally I haven't seen in my testing, so maybe it doesn't happen for POSTs)?

Bottom line: is it OK to use 401 in this context, or is there a better solution?

j0ni
  • 473
  • 1
  • 4
  • 6
  • 7
    It's not a RESTful API if you are using a cookie. REST services are stateless by definition. – Lukáš Lalinský Oct 24 '09 at 18:50
  • 1
    Fair point - I changed my description to REST-ish, rather than RESTful. So do you think the answer is either to correctly implement per-request authentication, or abandon my attempt at RESTishness? – j0ni Oct 24 '09 at 18:59
  • Hard to say, it depends on your application. The REST approach has some advantages. If you want to keep using the server-side session, I'd return 403 as tvanfosson said. – Lukáš Lalinský Oct 24 '09 at 19:02

2 Answers2

47

Typically, you'd send a 401 if the client can authenticate and solve the problem, but since you don't provide a way to authenticate in the API, I'd suggest returning a 403 error (forbidden) instead. This won't require the header and will indicate to the client that it is unable to access the service.

tvanfosson
  • 524,688
  • 99
  • 697
  • 795
  • 3
    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 for the refusal in the entity. If the server does not wish to make this information available to the client, the status code 404 (Not Found) can be used instead. (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) – Vicente Quintans Oct 10 '14 at 07:59
  • 2
    @vquintans 404 not found seems like it could be ambiguous in this case. Say the client requests a particular resource that may or may not exist but doesn't have the cookie? How would you interpret the 404 error? Did it fail because the resource was unavailable or with an authentication error. I'd stick with the response that clearly indicates the need for authorization. – tvanfosson Oct 10 '14 at 13:10
  • 1
    Yes, I agree. But in any case I think it is interesting to remark that possibility from the RFC. – Vicente Quintans Oct 10 '14 at 13:17
10

Return something like this:

HTTP/1.1 401 Unauthorized
Location: https://example.com/auth-app/login
yfeldblum
  • 65,165
  • 12
  • 129
  • 169
  • I second this one. The status header is what happened in the olden days with Basic authentication. The browser just shows the login dialog three times (and then the server returns "HTTP/1.1 XXX Forbidden"). – Mats Dec 24 '18 at 21:07