3

I want to authenticate to another site using HTTP Digest authorization in PHP script.

My function has as parameter just content of the WWW-Authenticate header and I want to generate correct response (Authorization header). I have found many examples that explain how to implement this the other way (browser authenticate to my script) but not this way. I am missing function that is able to parse WWW-Authenticate header content a generate response. Is there some standard function or common library that implements this?

Jiri
  • 16,425
  • 6
  • 52
  • 68
  • What do you use to connect to the site? cURL? – Milen A. Radev Jun 10 '09 at 12:42
  • I am connection using xmlrpc library. I receive WWW-Authenticate by calling one specific function of remote object and I have to pass standard response to another function. – Jiri Jun 10 '09 at 12:46
  • You can try my RESTful Client. It's basic but easy client for PHP with CI GET type support. url: https://github.com/corysus/restful_client – corysus Nov 06 '12 at 12:47

2 Answers2

6

Ok, no answer yet, I have investigated python implementation that lied around here and rewrite it to PHP. It is the simplest possible piece of code. Supports only md5 hashing, but works for me:

function H($param) {
    return md5($param);
}
function KD($a,$b) {
    return H("$a:$b");
}
function parseHttpDigest($digest) {
    $data = array();
    $parts = explode(", ", $digest);

    foreach ($parts as $element) {
        $bits = explode("=", $element);
        $data[$bits[0]] = str_replace('"','', $bits[1]);
    }
    return $data;
}

function response($wwwauth, $user, $pass, $httpmethod, $uri) {        
        list($dummy_digest, $value) = split(' ', $wwwauth, 2);    
        $x = parseHttpDigest($value);
        $realm = $x['realm'];        
        $A1 = $user.":".$realm.":".$pass;        
        $A2 = $httpmethod.":".$uri;

        if ($x['qop'] == 'auth') {
            $cnonce = time();
            $ncvalue = 1;
            $noncebit = $x['nonce'].":".$ncvalue.":".$cnonce.":auth:".H($A2);
            $respdig = KD(H($A1), $noncebit);
        }else {
            # FIX: handle error here
        }

        $base  = 'Digest username="'.$user.'", realm="';
        $base .= $x['realm'].'", nonce="'.$x['nonce'].'",';
        $base .= ' uri="'.$uri.'", cnonce="'.$cnonce;
        $base .= '", nc="'.$ncvalue.'", response="'.$respdig.'", qop="auth"';
        return $base;
    }

Usage:

# TEST
$www_header = 'Digest realm="TEST", nonce="356f2dbb8ce08174009d53c6f02c401f", algorithm="MD5", qop="auth"';
print response($www_header, "user", "password", "POST", "/my_url_query");
Jiri
  • 16,425
  • 6
  • 52
  • 68
  • Nicely done. Can you give a pointer on how to retrieve the www-authenticate header, i.e. the nonce? Thanks! – roesslerj Jul 03 '12 at 09:47
  • 1
    I had to search for it a bit, so: one can retrieve the www-authenticate header (i.e. the nonce) via get_headers($url) – roesslerj Jul 03 '12 at 11:55
1

Don't know of a ready-made client-side implementation in PHP; you have to implement the RFC as if your script were the browser, authenticating to a remote server. Wikipedia's page on HTTP Digest has a nice example.

(it's not that hard - a couple of MD5 hashes. Some gotchas I encontered when building the server-side: string delimiter is ":" (colon), request method is also a part of the hash)

Community
  • 1
  • 1
Piskvor left the building
  • 91,498
  • 46
  • 177
  • 222
  • I know how HTTP Digest works. Even better is to read RFC 2617 (http://tools.ietf.org/html/rfc2617), that describes all better than wikipedia, but I am looking for some already implemented function/library that can handle that. – Jiri Jun 10 '09 at 12:58
  • @Jiri: You're right, shoud've gone to the source. Let's see if something comes up - a Digest library would be useful to me, too. – Piskvor left the building Jun 10 '09 at 13:04