I'm in the midst of writing an app which needs to authenticate with a remote server using digest authentication before it can trade data with it. I was hoping to use drupal_http_request(), but that function does not support this type of authentication.

I initially started to hack the function to see if I could work it in there, but quickly got over my head with the jargon in the relevant RFC. However, from what I understand, it's something that the function should be able to handle easily.

Digest authentication starts when the client makes a request of the server. The server will respond with a 401 Unauthorized response, but will also include a header labelled "WWW-Authenticate," the value of which will contain "Digest" followed by various instructions, including a nonce string. The client then makes a request from the server again, this time including an "Authorization" header which includes the value of the "WWW-Authenticate," as well as a hash created from concatenation of the password and the nonce (…if I'm understanding things correctly). So the switch block at the end of the function's code would have something like this added to it:

<?php
   
case 401: // Unauthorized
       
if (isset($uri['user']) && !isset($headers['Authorization']) && isset($result->headers['WWW-Authenticate']) && strpos($result->headers['WWW-Authenticate'], 'Digest') === 0) {
           
// …Hashing voodoo…
           
$headers['Authorization'] = $result->headers['WWW-Authenticate'] . $voodoo;
           
$result = drupal_http_request($url, $headers, $method, $data, --$retry);
        }
        else {
           
$result->error = $text;
        }
?>

I'm thinking this could even be backported into a D6 release since it shouldn't change the functionality of the function for those not trying to connect to servers with digest authentication.

Perhaps if I grow smarter about this sort of thing and/or have some time to waste, I'll sit down and try figuring it out for myself some time, but for this project, I'll probably end up just rolling my own parallel function that uses PHP's curl library.

Comments

There is a good example of digest authentication in this Wikipedia article: http://en.wikipedia.org/wiki/Digest_access_authentication. Also see HTTP authentication with PHP.

Version:7.x-dev» 8.x-dev

Bumping to d8

There should be an extra option to tell the function which authentication type to use. This is required to prevent the function from trying the basic auth first (and thus sending the plain password over the wire).

This function is already a very big function. Adding multiple authentication methods won't help much. Is the next step to add "Negotiate" and "NTLM" in the same function? It is better to make it pluggable via hooks. Authentication scheme's may then be implemented in other modules. I suggest that only basic authentication goes in core because it is far more common than the others.

I'm open to a patch for httprl that implements this #1780566: support digest authentication

Version:8.x-dev» 7.x-dev

Moving back to 7.x as D8 has guzzle in it