302
Chapter 14 Implementing Authentication with PHP and MySQL
password back and forth to the browser with every page requested or delivered, this sen-
sitive information is being transmitted more often than necessary.
There are two good ways to tackle these problems: HTTP basic authentication and
sessions. Basic authentication overcomes the caching problem, but the browser still sends
the password to the browser with every request. Session control overcomes both of these
problems.We will look at HTTP basic authentication now, and examine session control
in Chapter 20,“Using Session Control in PHP,” and in more detail in Chapter 24,
“Building User Authentication and Personalization.”
Basic Authentication
Fortunately, authenticating users is a common task, so there are authentication facilities
built in to HTTP. Scripts or Web servers can request authentication from a Web browser.
The Web browser is then responsible for displaying a dialog box or similar device to get
required information from the user.
Although the Web server requests new authentication details for every user request,
the Web browser does not need to request the user’s details for every page.The browser
generally stores these details for as long as the user has a browser window open and
automatically resends them to the Web server as required without user interaction.
This feature of HTTP is called basic authentication.You can trigger basic authentication
using PHP, or using mechanisms built in to your Web server.We will look at the PHP
method, the Apache method, and the IIS method.
Basic authentication transmits a user’s name and password in plain text, so it is not
very secure. HTTP 1.1 contains a somewhat more secure method known as digest
authentication, which uses a hashing algorithm (usually MD5) to disguise the details of the
transaction. Digest authentication is supported by many Web servers, but is not supported
by a significant number of Web browsers. Digest authentication has been supported by
Microsoft Internet Explorer from version 5.0.At the time of writing, it is not supported
by any version of Netscape or Mozilla.
In addition to being poorly supported by installed Web browsers, digest authentication
is still not very secure. Both basic and digest authentication provide a low level of securi-
ty. Neither gives the user any assurance that she is dealing with the machine she intend-
ed to access. Both might permit a cracker to replay the same request to the server.
Because basic authentication transmits the user’s password as plain text, it allows any
cracker capable of capturing packets to impersonate the user for making any request.
Basic authentication provides a (low) level of security similar to that commonly used
to connect to machines via telnet or ftp, transmitting passwords in plaintext. Digest
authentication is a little more secure, encrypting passwords before transmitting them.
Using SSL and digital certificates, all parts of a Web transaction can be protected by
strong security.
If you want strong security, you should read the next chapter, Chapter 15,
“Implementing Secure Transactions with PHP and MySQL.” However, for many situa-
tions, a fast, but relatively insecure, method such as basic authentication is appropriate.
18 525x ch14 1/24/03 3:36 PM Page 302
303
Using Basic Authentication in PHP
Basic authentication protects a named realm and requires users to provide a valid
username and password. Realms are named so that more than one realm can be on the
same server. Different files or directories on the same server can be part of different
realms, each protected by a different set of names and passwords. Named realms also let
you group multiple directories on the one host or virtual host as a realm and protect
them all with one password.
Using Basic Authentication in PHP
PHP scripts are generally cross-platform, but using basic authentication relies on envi-
ronment variables set by the server. In order for an HTTP authentication script to run
on Apache using PHP as an Apache Module or on IIS using PHP as an ISAPI module, it
needs to detect the server type and behave slightly differently.The script in Listing 14.4
will run on both servers, but unlike most of the scripts in this book, it relies on your
php.ini file having register_globals turned on.
Listing 14.4 http.php—PHP Can Trigger HTTP Basic Authentication
<?php
// if we are using IIS, we need to set $PHP_AUTH_USER and $PHP_AUTH_PW
if (substr($SERVER_SOFTWARE, 0, 9) == 'Microsoft' &&
!isset($PHP_AUTH_USER) &&
!isset($PHP_AUTH_PW) &&
substr($HTTP_AUTHORIZATION, 0, 6) == 'Basic '
)
{
list($PHP_AUTH_USER, $PHP_AUTH_PW) =
explode(':', base64_decode(substr($HTTP_AUTHORIZATION, 6)));
}
// Replace this if statement with a database query or similar
if ($PHP_AUTH_USER != 'user' || $PHP_AUTH_PW != 'pass')
{
// visitor has not yet given details, or their
// name and password combination are not correct
header('WWW-Authenticate: Basic realm="Realm-Name"');
if (substr($SERVER_SOFTWARE, 0, 9) == 'Microsoft')
header('Status: 401 Unauthorized');
else
header('HTTP/1.0 401 Unauthorized');
echo '<h1>Go Away!</h1>';
echo 'You are not authorized to view this resource.';
}
18 525x ch14 1/24/03 3:36 PM Page 303
304
Chapter 14 Implementing Authentication with PHP and MySQL
else
{
// visitor has provided correct details
echo '<h1>Here it is!</h1>';
echo '<p>I bet you are glad you can see this secret page.</p>';
}
?>
The code in Listing 14.4 acts in a very similar way to the previous listings in this chap-
ter. If the user has not yet provided authentication information, it will be requested. If
she has provided incorrect information, she is given a rejection message. If she provides a
matching name-password pair, she is presented with the contents of the page.
The user will see an interface somewhat different from the previous listings.We are
not providing an HTML form for login information.The user’s browser will present her
with a dialog box. Some people see this as an improvement; others would prefer to have
complete control over the visual aspects of the interface.The login dialog box that
Internet Explorer provides is shown in Figure 14.4.
Listing 14.4 Continued
Figure 14.4 The user’s browser is responsible for the appearance
of the dialog box when using HTTP authentication.
Because the authentication is being assisted by features built in to the browser, the
browsers choose to exercise some discretion in how failed authorization attempts are
handled. Internet Explorer lets the user try to authenticate three times before displaying
the rejection page. Netscape will let the user try an unlimited number of times, popping
up a dialog box to ask,“Authorization failed. Retry?” between attempts. Netscape only
displays the rejection page if the user clicks Cancel.
As with the code given in Listing 14.1 and 14.2, we could include this code in pages
we wanted to protect, or automatically prepend it to every file in a directory.
18 525x ch14 1/24/03 3:36 PM Page 304
305
Using Basic Authentication with Apache’s .htaccess Files
Using Basic Authentication with Apache’s
.htaccess Files
We can achieve very similar results to the previous script without writing a PHP script.
The Apache Web server contains a number of different authentication modules that
can be used to decide the validity of data entered by a user.The easiest to use is
mod_auth, which compares name-password pairs to lines in a text file on the server.
In order to get the same output as the previous script, we need to create two separate
HTML files, one for the content and one for the rejection page.We skipped some
HTML elements in the previous examples, but really should include <html> and <body>
tags when we are generating HTML.
Listing 14.5 contains the content that authorized users see.We have called this file
content.html. Listing 14.6 contains the rejection page.We have called this
rejection.html.Having a page to show in case of errors is optional, but it is a nice,
professional touch if you put something useful on it. Given that this page will be shown
when a user attempts to enter a protected area but is rejected, useful content might
include instructions on how to register for a password, or how to get a password reset
and emailed if it has been forgotten.
Listing 14.5 content.html—Our Sample Content
<html><body>
<h1>Here it is!</h1>
<p>I bet you are glad you can see this secret page.</p>
</body></html>
Listing 14.6 rejection.html—Our Sample 401 Error Page
<html><body>
<h1>Go Away!</h1>
<p>You are not authorized to view this resource.</p>
</body></html>
There is nothing new in these files.The interesting file for this example is Listing 14.7.
This file needs to be called .htaccess, and will control accesses to files and any subdi-
rectories in its directory.
Listing 14.7 .htaccess—An .htaccess File Can Set Many Apache Configuration Settings,
Including Activating Authentication
ErrorDocument 401 /chapter14/rejection.html
AuthUserFile /home/book/.htpass
AuthGroupFile /dev/null
AuthName "Realm-Name"
AuthType Basic
require valid-user
18 525x ch14 1/24/03 3:36 PM Page 305
306
Chapter 14 Implementing Authentication with PHP and MySQL
Listing 14.7 is an .htaccess file to turn on basic authentication in a directory. Many
settings can be made in an .htaccess file, but the six lines in our example all relate to
authentication.
The first line
ErrorDocument 401 /chapter14/rejection.html
tells Apache what document to display for visitors who fail to authenticate.You can use
other ErrorDocument directives to provide your own pages for other HTTP errors such
as 404.The syntax is
ErrorDocument error_number URL
For a page to handle error 401, it is important that the URL given is publicly available.
It would not be very useful in providing a customized error page to tell people that their
authorization failed if the page is locked in a directory in which they need to successful-
ly authenticate to see.
The line
AuthUserFile /home/book/.htpass
tells Apache where to find the file that contains authorized users’ passwords.This is often
named
.htpass,but you can give it any name you prefer. It is not important what this
file is called, but it is important where it is stored. It should not be stored within the
Web tree—somewhere that people can download it via the Web server. Our sample
.htpass file is shown in Listing 14.8.
As well as specifying individual users who are authorized, it is possible to specify that
only authorized users who fall into specific groups may access resources.We have chosen
not to, so the line
AuthGroupFile /dev/null
sets our AuthGroupFile to point to /dev/null,a special file on Unix systems that is
guaranteed to be null.
Like the PHP example, to use HTTP authentication, we need to name our realm as
follows:
AuthName "Realm-Name"
You can choose any realm name you prefer, but bear in mind that the name will be
shown to your visitors.To make it obvious that the name in the example should be
changed, ours is named "Realm-Name".
Because a number of different authentication methods are supported, we need to
specify which authentication method we are using.
We are using Basic authentication as specified by this directive:
AuthType Basic
We need to specify who is allowed access.We could specify particular users, particular
groups, or as we have done, simply allow any authenticated user access.
18 525x ch14 1/24/03 3:36 PM Page 306