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

api, http, oauth, rest

Solution

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

Problem

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.

Original source