Chapter 16. HTTP authentication with PHP
The HTTP Authentication hooks in PHP are only available when
it is running as an Apache module and is hence not available
in the CGI version. In an Apache module PHP script, it is
possible to use the header() function to send an "Authentication
Required" message to the client browser causing it to
pop up a Username/Password input window. Once the user has
filled in a username and a password, the URL containing the
PHP script will be called again with the predefined variables
PHP_AUTH_USER, PHP_AUTH_PW, and AUTH_TYPE set to the user
name, password and authentication type respectively. These
predefined variables are found in the $_SERVER and $HTTP_SERVER_VARS
arrays. Only "Basic" authentication is supported.
See the header() function for more information.
PHP Version Note: Autoglobals, such as $_SERVER, became
available in PHP 4.1.0. $HTTP_SERVER_VARS has been available
since PHP 3.
An example script fragment which would force client authentication
on a page is as follows:
Example 16-1. 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>";
}
?>
Compatibility Note: Please be careful when coding the HTTP
header lines. In order to guarantee maximum compatibility
with all clients, the keyword "Basic" should be
written with an uppercase "B", the realm string
must be enclosed in double (not single) quotes, and exactly
one space should precede the 401 code in the HTTP/1.0 401
header line.
Instead of simply printing out PHP_AUTH_USER and PHP_AUTH_PW,
as done in the above example, you may want to check the
username and password for validity. Perhaps by sending a
query to a database, or by looking up the user in a dbm
file.
Watch out for buggy Internet Explorer browsers out there.
They seem very picky about the order of the headers. Sending
the WWW-Authenticate header before the HTTP/1.0 401 header
seems to do the trick for now.
As of PHP 4.3.0, in order to prevent someone from writing
a script which reveals the password for a page that was
authenticated through a traditional external mechanism,
the PHP_AUTH variables will not be set if external authentication
is enabled for that particular page and safe mode is enabled.
Regardless, REMOTE_USER can be used to identify the externally-authenticated
user. So, you can use $_SERVER['REMOTE_USER'].
Configuration Note: PHP uses the presence of an AuthType
directive to determine whether external authentication is
in effect.
Note, however, that the above does not prevent someone
who controls a non-authenticated URL from stealing passwords
from authenticated URLs on the same server.
Both Netscape Navigator and Internet Explorer will clear
the local browser window's authentication cache for the
realm upon receiving a server response of 401. This can
effectively "log out" a user, forcing them to
re-enter their username and password. Some people use this
to "time out" logins, or provide a "log-out"
button.