HTTP Authentication and Microsoft IIS / PHP ISAPI module

Eventum has a feature to provide RSS feeds of custom filters, which is basically a way to save advanced search parameters into a special URL that you can call out to check on results. Pretty useful feature, and a lot of people use that. However, we can’t simply have an open window into a potential confidential database of issues/bugs/tickets, so the RSS feed script authenticates the user with HTTP Auth, with the usual PHP way of doing things:

<?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 "Hello {$_SERVER['PHP_AUTH_USER']}.";
echo "You entered {$_SERVER['PHP_AUTH_PW']} as your password.";
}
?>

Everything works fine most of the times, but we started getting reports of problems from Microsoft IIS users. It turns out that PHP doesn’t automagically sets up the PHP_AUTH_* variables for you in some cases, and there’s even a quick mention of that on the documentation:

Another limitation is if you’re using the IIS module (ISAPI) and PHP 4, you may not use the PHP_AUTH_* variables but instead, the variable HTTP_AUTHORIZATION is available. For example, consider the following code: list($user, $pw) = explode(‘:’, base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));

However, that wasn’t true for a Microsoft IIS 6.0 that had configured PHP as a ISAPI module. Instead of getting a $_SERVER['HTTP_AUTHORIZATION'] variable like that, he would get this when doing var_dump($_SERVER):

array(30) {
["ALL_HTTP"]=> string(985) "HTTP_CONNECTION:keep-alive
HTTP_KEEP_ALIVE:300
HTTP_ACCEPT_CHARSET:ISO-8859-1,utf-8;q=0.7,*;q=0.7
HTTP_ACCEPT_ENCODING:gzip,deflate HTTP_ACCEPT_LANGUAGE:en-us,en;q=0.5
HTTP_AUTHORIZATION:Basic ********************************************"
}

So instead of simply using the $_SERVER variables, I had to manually handle the HTTP environment variables and get the proper value:

if ((!empty($_SERVER['ALL_HTTP'])) && (strstr($_SERVER['ALL_HTTP'], 'HTTP_AUTHORIZATION'))) {
preg_match('/HTTP_AUTHORIZATION:Basic (.*)/', $_SERVER['ALL_HTTP'], $matches);
if (count($matches) > 0) {
$pieces = explode(':', base64_decode($matches[1]));
$_SERVER['PHP_AUTH_USER'] = $pieces[0];
$_SERVER['PHP_AUTH_PW'] = $pieces[1];
}
}

That will do the trick.

2 Comments »

  1. Daniel Israel said,

    April 5, 2007 @ 12:44 pm

    Do you have to have register_globals enabled to use this? Mine doesn’t seem to work at all… I never get the HTTP_AUTHORIZATION back…

  2. German said,

    September 1, 2008 @ 8:28 am

    When copying from the page, single and double quotes are not standard (“””) for a PHP script (5 different types found) , had to search and replace all:

    ‘PHP_AUTH_USER’
    ’WWW-Authenticate: Basic realm=”My Realm”‘
    ’HTTP/1.0 401 Unauthorized’
    ‘Text to send if user hits Cancel button’
    “Hello {$_SERVER['PHP_AUTH_USER']}.”
    “You entered {$_SERVER['PHP_AUTH_PW']} as your password.”

    (the script works fine anyway)

    Regards

RSS feed for comments on this post · TrackBack URI

Leave a Comment