Various articles (1, 2) I discovered make this look easy enough:
WebRequest request = HttpWebRequest.Create(url);
var credentialCache = new CredentialCache();
credentialCache.Add(
new Uri(url), // request url
"Digest", // authentication type
new NetworkCredential("user", "password") // credentials
);
request.Credentials = credentialCache;
However, this only works for URLs without URL parameters. For example, I can download http://example.com/test/xyz.html
just fine, but when I attempt to download http://example.com/test?page=xyz
, the result is a 400 Bad Request message with the following in the server's logs (running Apache 2.2):
Digest: uri mismatch - </test> does not match request-uri </test?page=xyz>
My first idea was that the digest specification requires URL parameters to be removed from the digest hash -- but removing the parameter from the URL passed to credentialCache.Add()
didn't change a thing. So it must be the other way around and somewhere in the .NET framework is wrongly removing the parameter from the URL.
You said you removed the querystring paramters, but did you try going all the way back to just the host? Every single example of CredentialsCache.Add() I've seen seems to use only the host, and the docs for CredentialsCache.Add() list the Uri parameter as "uriPrefix", which seems telling.
In other words, try this out:
Uri uri = new Uri(url);
WebRequest request = WebRequest.Create(uri);
var credentialCache = new CredentialCache();
credentialCache.Add(
new Uri(uri.GetLeftPart(UriPartial.Authority)), // request url's host
"Digest", // authentication type
new NetworkCredential("user", "password") // credentials
);
request.Credentials = credentialCache;
If this works, you will also have to make sure that you don't add the same "authority" to the cache more than once... all requests to the same host should be able to make use of the same credential cache entry.