You’re a client talking to an http server, and you get a 401: unauthorized.

How are you supposed to know how to authenticate?

RFC 7235 has you covered. Let’s review.

1. 401 and Authorization header

Along with the 401: unauthorized http response, the server must be setting the following header telling you how to authenticate:

  • www-authenticate: <challenge>,<challenge>

Where challenge tells you which kind of authentication is expected. More than one challenge can be received, meaning that the client may chose one of them.

1.1. Challenge and Schemes

Challenges are linked to authorization schemes, which are standardized by IANA.org.

Each challenge has the following format:

scheme <options>

where the accepted options depend on the scheme itself.

1.2. Basic Scheme

With Basic Authentication, the only required option is realm, and the scheme name is Basic:

GET /resources HTTP/2
Host: website.org

HTTP/2 401 Unauthorized
WWW-Authenticate: Basic realm="whatever"

This indicates that you need to send an Authorization header:

GET /resources HTTP/2
Host: website.org
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQK

HTTP/2 200 Ok

Note: What is the realm option? Really depends on the scheme, but for Basic it’s a way to let specific the scope/partition onto which this authentication will work for. Imagine something like some servers needing one kind of username and password (for example, a github account), and some servers needing a different kind of username and password (for example, a windows account): the server can use the realm to indicate to the client that this is the case.

1.3. OAuth2 and Bearer scheme

In the wild, you’re more likely to encounter the OAuth 2 nowadays, with its Bearer scheme:

GET /resources HTTP/2
Host: website.org

HTTP/2 401 Unauthorized
WWW-Authenticate: Bearer realm="whatever", scope="openid profile email"

2. 407 and Proxy-Authorization header

If the client is talking to a proxy, the same is true, but with a code 407, and header Proxy-Authenticate header:

GET /resources HTTP/2
Host: website.org

HTTP/2 407 Proxy Authentication Required
Proxy-Authenticate: Basic realm="Access to internal site"

This time, you the client needs to fill-in the Proxy-Authorization header:

GET /resources HTTP/2
Host: website.org
Proxy-Authorization: Basic cHJveHktdXNlcm5hbWU6cHJveHktcGFzc3dvcmQK

HTTP/2 200 Ok

Note: the client may have to proxy both the Authorization header and the Proxy-Authorization header in some scenarios.

3. Reality and shortcomings

In reality, not all servers will actually return a WWW-Authenticate header, leaving the client in the dark about how to go forward with the authentication.

Even if the server does return such a header, the specification is quite open, and doesn’t require telling the client how or where to get the authorization data.

For example, the realm part of the Basic scheme could tell the client which type of account is required, but the client and server must understand each other about its meaning.

In the OAuth 2, the scope option of the Bearer scheme is often used to indicate which kind of rights is required in the token expected by the server, but the server doesn’t tell you what is the endpoint to target to generate such a token.

Yet, if you work on a server, make sure your server does return a WWW-Authenticate.