Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Digest HTTP Authentication example not working, why?

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.

like image 719
Erik B Avatar asked Mar 02 '11 21:03

Erik B


People also ask

How does HTTP digest authentication work?

Digest authentication is another authentication type specified in HTTP 1.1. Unlike basic authentication, digest authentication does not require the password to be transmitted. Rather, the client takes the username and password and uses the MD5 hashing algorithm to create a hash, which is then sent to the SQL Server.

How does PHP authentication work?

After receiving user authentication details in PHP, it compares the form data with the user database by executing a query by using the connection object. The query binds the username entered by the user via HTML form. Then, it verifies the password hash with the entered password to return the authentication results.

What types of HTTP authentication are supported by PHP?

Only "Basic" and "Digest" authentication methods are supported.

What is enable digest authentication?

Digest access authentication is one of the agreed-upon methods a web server can use to negotiate credentials, such as username or password, with a user's web browser. This can be used to confirm the identity of a user before sending sensitive information, such as online banking transaction history.


2 Answers

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.

like image 102
DanMan Avatar answered Sep 17 '22 09:09

DanMan


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
like image 28
Thierry Marianne Avatar answered Sep 17 '22 09:09

Thierry Marianne