[ Team LiB ] Previous Section Next Section

Recipe 21.1 Authenticating

21.1.1 Problem

You want to verify the username and password supplied by users who are authenticating themselves.

21.1.2 Solution

Get the password with $r->get_basic_auth_pw, and the username with $r->connection->user. Indicate success by returning OK. Indicate failure by calling $r->note_basic_auth_failure and returning AUTH_REQUIRED.

package Your::Authentication::Package;
use Apache::Constants ':common';

sub handler {
  my $r = shift;

  return OK unless $r->is_main;    # skip for subrequests

  my ($res, $sent_pw) = $r->get_basic_auth_pw;
  if ($res != OK) {
    $r->note_basic_auth_failure;
    return $res;
  }

  my $user = $r->user;

  # check username and password, setting $failed if they don't match

  if ($failed) {
    $r->note_basic_auth_failure;
    return AUTH_REQUIRED;
  }

  return OK;
}

Install the handler for a directory or set of files with:

# the realm
AuthName "Holiday Photos"
# next line shouldn't be changed
AuthType Basic
PerlAuthenHandler Your::Authentication::Package
require valid-user

21.1.3 Description

The realm is what the user sees when their browser prompts for a username and password. If you set the realm to "Holiday Photos", the user is prompted to "enter username and password for Holiday Photos". You need at least one require directive to trigger the call to the authentication handler.

When you invoke $r->get_basic_auth_pw, Apache processes any authentication information sent by the client. Therefore you can't call $r->user before you call $r->get_basic_auth_pw (well, you can, but you won't get anything back).

The call to $r->get_basic_auth_pw returns two values, a status code and a password. If the status is OK, the browser agreed to authenticate and provided information. If the status is DECLINED, either the area isn't protected by basic authentication or there's no AuthType specified in httpd.conf. If the status is SERVER_ERROR, there's no realm defined for this area. If the status is AUTH_REQUIRED, the browser mangled or omitted basic authentication. If you decide to return AUTH_REQUIRED, first call $r->note_basic_auth_failure to ensure Apache sends realm information to the browser.

The status code returned from $r->get_basic_auth_pw tells you whether the browser knows to authenticate these pages. When the browser sends no authentication information, you respond "no password, no access." To do this, note the authentication failure and return the AUTH_REQUIRED that $r->get_basic_auth_pw gave you.

We invoke $r->is_main to learn whether we're the main request. Apache often makes subrequests, and there's no point in doing the (potentially slow) authentication lookup for the subrequests. This doesn't result in less security, since if the authentication fails for the main request, the content handler isn't run. This avoids messy problems like recursion and multiple attempts to parse POST data.

21.1.4 See Also

The Apache.pm manpage; Writing Apache Modules with Perl and C; Recipe 13.3 in mod_perl Developer's Cookbook

    [ Team LiB ] Previous Section Next Section