8
votes

When building a REST API that doesn't use HTTP basic authentication (but something else like an api-key) and the client provides invalid credentials, what HTTP Status Code are you supposed to return? 401 Unauthorized or 403 Forbidden?

The IANA HTTP Status Code Registry lists RFC7235, Section 3.1 as responsible for "401 Unauthorized", where it states:

The server generating a 401 response MUST send a WWW-Authenticate header field

Does that mean that a REST API should only ever return a 401 when using HTTP basic authentication but not when for example using authentication via an api-key?

Django seems to agree:

HTTP 401 responses must always include a WWW-Authenticate header, that instructs the client how to authenticate. HTTP 403 responses do not include the WWW-Authenticate header.

The kind of response that will be used depends on the authentication scheme.

While Richardson seems to disagree:

401 (“Unauthorized”)
Importance: High.
The client tried to operate on a protected resource without providing the proper authentication credentials. It may have provided the wrong credentials, or none at all. The credentials may be a username and password, an API key, or an authentication token—whatever the service in question is expecting. It’s common for a client to make a request for a URI and accept a 401 just so it knows what kind of credentials to send and in what format. [...]

1
You should, for various reasons, avoid using API keys in headers. See my discussion here: soabits.blogspot.dk/2014/02/… and Eran Hammers discussion here: hueniverse.com/2010/09/29/…Jørn Wildt
Just found what is basically the same question. It didn't turn up in my previous searches: stackoverflow.com/questions/17687876/…mb21

1 Answers

11
votes

You are assuming that the www-authenticate value needs to be basic. You can return a different value like "API-key" as the type of auth that needs to happen. So feel free to return 401 and www-authenticate header with some other value. You can even return multiple headers with different values indicating the different types of authentication that your app supports.