PHP Digest HTTP Authentication example not working, why?
Asked Answered
N

2

11

So I decided to use digest HTTP authentication for my REST API. I googled it and found an entry in the PHP manual with an example of how to do it. So I copy the script, put it in index.php on my server, open the page in the browser, after entering my credentials the browser asks for them again and I'm stuck in an infinite loop of entering credentials. The script is included below and can be found here.

Example #7 Digest HTTP Authentication example

<?php
$realm = 'Restricted area';

//user => password
$users = array('admin' => 'mypass', 'guest' => 'guest');


if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
    header('HTTP/1.1 401 Unauthorized');
    header('WWW-Authenticate: Digest realm="'.$realm.
           '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');

    die('Text to send if user hits Cancel button');
}


// analyze the PHP_AUTH_DIGEST variable
if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) ||
    !isset($users[$data['username']]))
    die('Wrong Credentials!');


// generate the valid response
$A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]);
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
$valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);

if ($data['response'] != $valid_response)
    die('Wrong Credentials!');

// ok, valid username & password
echo 'Your are logged in as: ' . $data['username'];


// function to parse the http auth header
function http_digest_parse($txt)
{
    // protect against missing data
    $needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
    $data = array();
    $keys = implode('|', array_keys($needed_parts));

    preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $txt, $matches, PREG_SET_ORDER);

    foreach ($matches as $m) {
        $data[$m[1]] = $m[3] ? $m[3] : $m[4];
        unset($needed_parts[$m[1]]);
    }

    return $needed_parts ? false : $data;
}
?>

I also tried basic authentication and that worked perfectly.

Example #6 Basic HTTP Authentication example

<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
    header('WWW-Authenticate: Basic realm="My Realm"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'Text to send if user hits Cancel button';
    exit;
} else {
    echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
    echo "<p>You entered {$_SERVER['PHP_AUTH_PW']} as your password.</p>";
}
?>

It seems like $_SERVER['PHP_AUTH_DIGEST'] is always empty.

Is there something wrong with the script or is my environment funky and if so how do I fix it?

EDIT: There is nothing wrong with the script. The fault lies with the server. If anyone knows what could possibly cause this, please let me know.

Nial answered 2/3, 2011 at 21:14 Comment(5)
If its any help, I took your exact code from above and put it into a test page on my server and and it works perfectly (the digest auth portion), so it must be a configuration issue of some sort. moditekka.com/phpauth.phpCuirbouilli
Also, are you closing the browser entirely (all tabs, all windows) between attempts? It will store your first attempt in a cookie and not prompt you again until you do that.Cuirbouilli
Thank you, Infotekka! Now I just need to figure out what's wrong with the server.Nial
I am also facing this issue (on free.fr server) ... btw: i needed to change it : - uniqid() + uniqid("") @Cuirbouilli : what version of php are you running ?Blader
In that case you may want to check your logs and ask on serverfault.comOrnament
K
7

Digest authentication is a separate Apache module that's often not installed on servers - especially with cheap hosting companies. It needs to be enabled to make use of it though.

http://httpd.apache.org/docs/current/mod/mod_auth_digest.html

It depends on your distribution how to install it, if you're using Linux. On my Ubuntu Linux it was enough to create a symbolic link of the module from the deactivated modules folder to the activated modules one run sudo a2enmod auth_digest on the shell. That, and restarting Apache, of course.

I don't know about Windows.

Kaylil answered 20/4, 2011 at 17:0 Comment(0)
N
1

Do you have mod_headers loaded within Apache (I assume your server run Apache)?

You might figure it out by using the following command line (which execution might require privileges):

httpd -M | grep head
Newsworthy answered 4/4, 2011 at 19:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.