Authenticating (Perl Cookbook, 2nd Edition)

## 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

Copyright © 2003 O'Reilly & Associates. All rights reserved.