the Chromium logo

The Chromium Projects

SPDY Server and Proxy Authentication

Support for Server and Proxy Authentication in SPDY is very similar to Server and Proxy Authentication in HTTP.

Server Authentication

When a client sends a request to an origin server that requires authentication, the server can reply with a 401 Unauthorized" response, and a WWW-Authenticate header that defines the authentication scheme to be used. The client then retries the request with an Authorization header appropriate to the specified authentication scheme.

There are four options for sever authentication, Basic, Digest, NTLM and Negotiate (SPNEGO). The first two options were defined in RFC 2617, and are stateless. The second two options were developed by Microsoft and specified in RFC 4559, and are stateful; otherwise known as multi-round authentication, or connection authentication.

Stateless Authentication

Both Basic and Digest Server Authentication are stateless. These schemes define ways for the browser to encode a username and password in the HTTP request which the server can verify. In the case of Basic Auth, the client simply base64 encodes the password. In the case of Digest, the client hashes the username, password, and a variety of other attributes together. Once a server requests Basic or Digest Authentication, the client is able to generate a correct Authorization header for any subsequent request to the same server.

Basic and Digest authentication is handled in SPDY in much the same way as with HTTP. Here is a sample SPDY session using Basic authentication:

 Client                        Server
 ------                        ------
 *** Client makes initial, unauthenticated request to the server.
   |------------------------------>|
   | 1) SYN_STREAM                 |
   |    stream_id = 1              |
   |    url = http://example.com/a |
   |                               |
   |<------------------------------|
   | 2) SYN_REPLY                  |
   |    stream_id = 1              |
   |    status = 401               |
   |    www-authenticate = Basic   |
   |                               |
 *** Client retries request with authorization header.
   |------------------------------>|
   | 3) SYN_STREAM                 |
   |    stream_id = 3              |
   |    url = http://example.com/a |
   |    authorization = Basic XXX  |
   |<------------------------------|
   | 4) SYN_REPLY                  |
   |    stream_id = 3              |
   |    status = 200               |
   |                               |
 *** Client request next resource with authorization header.
   |------------------------------>|
   | 5) SYN_STREAM                 |
   |    stream_id = 5              |
   |    url = http://example.com/b |
   |    authorization = Basic XXX  |
   |<------------------------------|
   | 4) SYN_REPLY                  |
   |    stream_id = 5              |
   |    status = 200               |
   |                               |

Stateful Authentication

The NTLM and Negotiate Authentication scheme are more complicated. Instead of enabling the browser to generate an Authorization header which can be used for subsequent requests to the server, these schemes attempt to authenticate the connection. After the authentication is complete, the server marks the connection as authorized, and the client sends subsequent requests without any Authorization header.

Multi-round authentication is handled in SPDY in much the same way as with HTTP. A new stream is created for each round in the process, corresponding to a request/response pair in the HTTP process.

 Client                        Server
 ------                        ------
 *** Client makes initial, unauthenticated request to the server.
   |---------------------------------->|
   | 1) SYN_STREAM                     |
   |    stream_id = 1                  |
   |    url = http://example.com/a     |
   |                                   |
   |<----------------------------------|
   | 2) SYN_REPLY                      |
   |    stream_id = 1                  |
   |    status = 401                   |
   |    www-authenticate = Negotiate   |
   |                                   |
 *** Client retries request with authorization header.
   |---------------------------------->|
   | 3) SYN_STREAM                     |
   |    stream_id = 3                  |
   |    url = http://example.com/a     |
   |    authorization = Negotiate AA   |
   |<----------------------------------|
   | 4) SYN_REPLY                      |
   |    stream_id = 3                  |
   |    status = 401                   |
   |    www-authenticate = Negotiate BB|
   |                                   |
 *** Client retries request with authorization header.
   |---------------------------------->|
   | 3) SYN_STREAM                     |
   |    stream_id = 3                  |
   |    url = http://example.com/a     |
   |    authorization = Negotiate CC   |
   |<----------------------------------|
   | 4) SYN_REPLY                      |
   |    stream_id = 3                  |
   |    status = 200                   |
   |    www-authenticate = Negotiate DD|
   |                                   |
 *** Client request next resource without authorization header.
   |---------------------------------->|
   | 5) SYN_STREAM                     |
   |    stream_id = 5                  |
   |    url = http://example.com/b     |
   |                                   |
   |<----------------------------------|
   | 4) SYN_REPLY                      |
   |    stream_id = 5                  |
   |    status = 200                   |
   |                                   |

However, one difference in how stateful authentication is handled between HTTP and SPDY results from the multiplexed nature of SPDY sessions. With a single SPDY session, a client can sent multiple requests in parallel before receiving the first response. This complicates the stateful authentication schemes which are attempting to perform a single authentication of the connection. If the server receives two requests (streams 1 and 3) on an unauthenticated session, it will reply 401 Unauthorized to each stream. However, it is not entirely clear how the authentication should continue.

One option would be for the client to complete the authentication on the first unauthorized stream and then assume that the connection will then be authenticated and continue issuing requests without authorization headers. However, it is possible for different resources on the same server to require different authentication. These resources would need to specify different "realms" when requesting authentication. When the client receives a 401, it would need to be aware of any outstanding authentication transaction for that same realm, and wait for it to complete.

An alternative option would be for the client to complete the authentication for both unauthorized streams. However, as currently specified, there is no obvious way to distinguish the 2nd attempt to request the first resource from the 2nd attempt to request the second resource. It is possible the the URL in the headers might be identical. It would seem to require that the client pass a X-Associated-Stream, or X-Authorization-Context header in each subsequent authentication request so the server is able to correctly understand the context of the request.

Proxy Authentication

When a client sends a request to a proxy server that requires authentication, the same basic protocol is used. Instead of a 401 Unauthorized response, the proxy can reply with a 407 Proxy Authentication Required response, and a Proxy-Authenticate header instead of an Authenticate. The client then retries the request with a Proxy-Authorization header in place of an Authorization header.