PHP

Managing HTTP Authentication with PHP

Rather than configuring Apache to authenticate requests, PHP scripts can manage the HTTP authentication challenge directly. Scripts can be written to test the $PHP_AUTH_USER and $PHP_AUTH_PW variables and send a response containing the WWW-Authenticate header to challenge the browser. When a request contains a username and password, the script can authenticate and authorize the request using any logic that is required. In Example 9-4 the user credentials set in the $PHP_AUTH_USER and $PHP_AUTH_PW variables are passed to the function authenticated( ). This function uses the unsophisticated authentication scheme of checking that the password is the same as the username. In the next section we show how to implement a secure scheme that stores passwords in a database.

Example 9-4. Script generates an unauthorized response if credentials aren't in request
<?php
function authenticated($username, $password)
{
  // If either the username or the password are
  // not set, the user is not authenticated
  if (!isset($username) || !isset($password))
    return false;
  // If the username is the same as the password
  // then the user is authenticated
  if ($username == $password)
    return true;
  else
    return false;
}
//Main --------
if(!authenticated($PHP_AUTH_USER, $PHP_AUTH_PW))
{
  // No credentials found - send an unauthorized
  // challenge response
  header("WWW-Authenticate: Basic realm=\"Flat Foot\"");
  header("HTTP/1.0 401 Unauthorized");
  // Set up the body of the response that is
  // displayed if the user cancels the challenge
  ?>
  <!DOCTYPE HTML PUBLIC
    "-//W3C//DTD HTML 4.0 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd" >
   <html>
     <head>
       <title>Web Database Applications</title>
     </head>
     <body>
       <h2>You need a username and password to
               access this service</h2>
       <p>If you have lost or forgotten your
               password, tough!
     </body>
  </html>
  <?php
  exit;
}
// The response to authorized users
?>
<!DOCTYPE HTML PUBLIC
   "-//W3C//DTD HTML 4.0 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd" >
<html>
  <head>
    <title>Web Database Applications</title>
  </head>
  <body>
    <h2>Welcome!</h2>
  </body>
</html>

The authenticated( ) function returns false if either the $username or $password hasn't been set, or if the two values aren't the same. If the user credentials fail the test, you respond with the header field WWW-Authenticate with the encoding scheme Basic and the realm name Flat Foot. You can also set the response line to include the status code 401 Unauthorized. The PHP manual suggests sending the WWW-Authenticate header before the HTTP/1.0 401Unauthorized header to avoid problems with some versions of Internet Explorer browsers.

The first time a browser requests this page, the script sends a challenge response containing the 401 Unauthorized header field. If the user cancels the authentication challenge, usually by clicking the cancel button in a dialog box that collects the credentials, the HTML encoded in the challenge response is displayed.

While the script shown in Example 9-4 duplicates much of the HTML used for the authorized response and the challenge response, you can't simplify the script by putting the common HTML at the start of the file. Because the script calls the header( ) function when credentials aren't included in the request or the supplied credentials don't authenticate, you can't output any of the response body until you know if the user has authenticated.