Search code examples
c++authenticationdigestdigest-authenticationhttp-digest

How to get Digest authentication right


I try to write a C++-application and I have to do HTTP Digest Authentication. The problem is not primarily about C++, but about the fact, that the connection is not being established. The website I try to access is the following: httpbin.org/digest-auth/auth/user/passwd .

Consider the following server response to a simple GET /digest-auth/auth/user/passwd:

HTTP/1.1 401 UNAUTHORIZED Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: * Content-Type: text/html; charset=utf-8 Date: Mon, 08 Sep 2014 15:10:09 GMT Server: gunicorn/18.0 Set-Cookie: fake=fake_value Www-Authenticate: Digest realm="[email protected]", nonce="2a932bfb1f9a748a7b5ee590d0cf99e0", qop=auth, opaque="2d09668631b42bff8375523e7b27e45e" Content-Length: 0 Connection: keep-alive

A1 is then computed to be user:[email protected]:passwd and is hashed to 4de666b60f91e2444f549243bed5fa4b which I will refer to as HA1. A2 is computed to be GET:/digest-auth/auth/user/passwd and hashed to b44272ea65ee4af7fb26c5dba58f6863 which I will refer to as HA2.

With this information, the response is computed as HA1:nonce:1:ac3yyj:auth:HA2, where HA1 and HA2 are the values we have just computed and nonce is taken from the server response above, which is in total: 4de666b60f91e2444f549243bed5fa4b:2a932bfb1f9a748a7b5ee590d0cf99e0:1:ac3yyj:auth:b44272ea65ee4af7fb26c5dba58f6863. The hash of that is 55f292e183ead0810528bb2a13b98e00.

Combining all that information should be sufficient to establish a http-connection using digest authentication. However, the following request is declined by the server and answered with another HTTP/1.1 401.

GET /digest-auth/auth/user/passwd HTTP/1.1 Host: httpbin.org Authorization: Digest username="user", realm="[email protected]",nonce="2a932bfb1f9a748a7b5ee590d0cf99e0",uri="/digest-auth/auth/user/passwd",qop=auth,nc=1,cnonce="ac3yyj",response="55f292e183ead0810528bb2a13b98e00",opaque="2d09668631b42bff8375523e7b27e45e"

Note that the formatting does not show the structure of the request. The block from Authorization to opaque is actually one line.

Feel free to re-do the md5-calculation - but I have redone the calculations manually and got the same hashes as my program did. I used that tool (http://md5-hash-online.waraxe.us/) for the manual computations.

Am I missing something obvious here, probably misinterpreting the standard in a way? Why can't I get authorized?


Solution

  • Finally got it. The authentication itself is completely correct.

    The server demands a cookie to be set. Apparently one must show that cookie in the reponse, too. That explains why firefox (being a browser) can authenticate correctly while curl and lwp-request can't albeit sticking to the standard - RFC said nothing about cookies. Why do we have standards, that noone cares for?

    Anyway, appending Cookie: fake=fake_value to the header solves the problem.