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?
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.