-
-
Save funkatron/949952 to your computer and use it in GitHub Desktop.
<?php | |
$url = 'http://domain.foo'; | |
$uri = '/assets'; | |
$username = 'testyser'; | |
$password = 'somepassword'; | |
$method = 'GET'; | |
$ht = new HttpRequest($url.$uri, HttpRequest::METH_GET); | |
$ht->send(); | |
print_r($ht->getRawRequestMessage()); | |
print_r($ht->getRawResponseMessage()); | |
$auth_resp_header = $ht->getResponseHeader('WWW-Authenticate'); | |
$auth_resp_header = explode(',', preg_replace("/^Digest/i", "", $auth_resp_header)); | |
$auth_pieces = array(); | |
foreach ($auth_resp_header as &$piece) { | |
$piece = trim($piece); | |
$piece = explode('=', $piece); | |
$auth_pieces[$piece[0]] = trim($piece[1], '"'); | |
} | |
print_r($auth_pieces); | |
// build response digest | |
$nc = str_pad('1', 8, '0', STR_PAD_LEFT); | |
$cnonce = '0a4f113b'; | |
$A1 = md5("{$username}:{$auth_pieces['realm']}:{$password}"); | |
$A2 = md5("{$method}:{$uri}"); | |
$auth_pieces['response'] = md5("{$A1}:{$auth_pieces['nonce']}:{$nc}:{$cnonce}:{$auth_pieces['qop']}:${A2}"); | |
$digest_header = "Digest username=\"{$username}\", realm=\"{$auth_pieces['realm']}\", nonce=\"{$auth_pieces['nonce']}\", uri=\"{$uri}\", cnonce=\"{$cnonce}\", nc={$nc}, qop=\"{$auth_pieces['qop']}\", response=\"{$auth_pieces['response']}\", opaque=\"{$auth_pieces['opaque']}\", algorithm=\"{$auth_pieces['algorithm']}\""; | |
$ht = new HttpRequest($url.$uri, HttpRequest::METH_GET); | |
$ht->setHeaders(array('Authorization'=>$digest_header)); | |
$ht->send(); | |
print_r($ht->getRawRequestMessage()); | |
print_r($ht->getRawResponseMessage()); |
Thank you for providing this code example. It was extremely helpful in setting up my own Digest authentication, along with a reading of Understanding HTTP Digest Access Authentication.
I found a flaw in the way you parse the original response header. It's possible that the "WWW-Authenticate" header parameters can contain a =
character in their values. Your call to explode()
causes the value to be parsed incorrectly where everything after the first =
in the value is discarded.
Here's an example, nonce="359211dc26d108:32g/mkd52jp+v2/cGj33Tg=="
Your code would make the value of nonce
be 359211dc26d108:32g/mkd52jp+v2/cGj33Tg
(the ==
is missing)
Here's where the flaw is:
foreach ($auth_resp_header as &$piece) {
$piece = trim($piece);
$piece = explode('=', $piece);
$auth_pieces[$piece[0]] = trim($piece[1], '"');
}
Here's a way to make sure the whole value stays intact:
foreach ($auth_resp_header as $piece) {
$piece = explode('=', trim($piece));
$key = array_shift($piece);
$value = trim(implode('=', $piece), '"');
$auth_pieces[$key] = $value;
}
(Alternatively, you could also use preg_match()
to do the parsing if you are comfortable with regular expressions)
Thanks for this.
If anyone else comes across this and lacks the HttpRequest library, you should install it as so:
sudo pecl install -f pecl_http-1.7.6
And then add the following to your php.ini file:
extension=http.so