Archive

Archive for February, 2009

PerlAuthenHandler

February 22nd, 2009

Among other things, mod_perl allows you to write authentication handlers that fit nicely into Apache’s authentication scheme. A Perl authentication handler is a Perl module that decides whether a given user gets access to a resource or not. How you determine whether the user is allowed or denied access is up to you.

The mod_perl documentation comes with a sample that checks the length of the username+space+password supplied by a user and allows the user access only if the length is 14 characters long. Here is what the code looks like:

  package MyApache2::SecretLengthAuth;

  use strict;
  use warnings;

  use Apache2::Access ();
  use Apache2::RequestUtil ();

  use Apache2::Const -compile => qw(OK DECLINED HTTP_UNAUTHORIZED);

  use constant SECRET_LENGTH => 14;

  sub handler {
      my $r = shift;

      my ($status, $password) = $r->get_basic_auth_pw;
      return $status unless $status == Apache2::Const::OK;

      return Apache2::Const::OK
          if SECRET_LENGTH == length join " ", $r->user, $password;

      $r->note_basic_auth_failure;
      return Apache2::Const::HTTP_UNAUTHORIZED;
  }

  1;

And you hook this handler up in your apache2.conf as:

  <Location / >
      PerlAuthenHandler MyApache2::SecretLengthAuth
      AuthType Basic
      AuthName "The Gate"
      Require valid-user
  </Location>

As the documentation points out, the authentication handler can be configured for any sub section of the site, it doesn’t matter if it is served by a mod_perl response handler or not.

Now obviously in real life, you’d want an authentication handler that does a little more – like verify the password supplied by the user against a database or LDAP . Here is a version that I wrote that uses Perl’s Net::POP3 package to verify user’s credential against a POP 3 server.

package Apache::PopAuth;

use strict;
use warnings;
use Net::POP3;

use Apache2::Access ();
use Apache2::RequestUtil ();
use Apache2::RequestRec ();
use Apache2::Const -compile => qw(OK DECLINED HTTP_UNAUTHORIZED);

sub handler {
    my $r = shift;
    my ($status, $password) = $r->get_basic_auth_pw;
    my $user = $r->user;

    return $status unless $status == Apache2::Const::OK;

    return Apache2::Const::OK
	   if valid_user($user, $password);

    $r->note_basic_auth_failure;
    return Apache2::Const::HTTP_UNAUTHORIZED;
}

sub valid_user {
    my($user, $password) = @_;
    my $pop = Net::POP3->new('pop.yourdomain.com');
    my $status = $pop->login($user, $password);
    $pop->quit();
    return defined($status);
}
1;

This saves you from having to maintain a separate set of users on your web server and passes on the baton of user management to the POP server. One word of caution – this just proof of concept code and I am not sure on well it will scale outside a small intranet.

perl ,