[Melbourne-pm] Apache auth and one time passwords.

Rick Measham rickm at isite.net.au
Wed Mar 9 20:10:07 PST 2005


Daniel Pittman wrote:
> I have a couple of web based systems that I would like to protect with a
> one time password tool, and being lazy, I want to use the work someone
> else has done to achieve this.

As you're the one who introduced me to perl-based apache authentication, 
  I feel I should reply :)

The attached solution is a simple hack on something I've done here at 
work. Normally I select the user from the database. In this case, I 
delete them. That way, if they exist I get a positive response from the 
delete and I cache them so they can keep accessing the site until their 
session expires (you'll notice I refresh the session on each request).

The solution does not rely on cookies, but instead relies on the browser 
not forgetting it's auth details for the site :)


N.B. The attached code ran perfectly in my head, but has not been tested 
on any other version of perl/apache.

Cheers!
Rick Measham

-------------- next part --------------
package Auth::OTP;
 
use strict;
use Apache::Constants qw(:common);
use Cache::FileCache;
use DBI;

require '/etc/httpd/lib/perl/config.pm';
my $DBH = DBI->connect(
	$config::db_dsn, 
	$config::db_user, 
	$config::db_pass
) or die $DBI::errstr;

my $CACHE = Cache::FileCache->new({
	namespace          => 'namespace',
	username           => 'otp',
	default_expires_in => $config::session_expire,
});

sub handler {
     my $r = shift;
     
     # get user's authentication credentials
     my($res, $sent_pw) = $r->get_basic_auth_pw;
     return $res if $res != OK;
     my $user = $r->connection->user;
     
     my $reason = authenticate($r, $user, $sent_pw);
  
     if($reason) {
        $r->note_basic_auth_failure;
        $r->log_reason($reason, $r->filename);
        return AUTH_REQUIRED;
     }
     return OK;
}

sub authenticate {
	my ($r, $user, $password) = @_;

	return 'No Database Connection' unless $DBH and $DBH->isa('DBI::db'); # No auth if we can't get to the DB!
	
	# Check the cache for the user:
	if ($user eq $CACHE->get($password)) {
		$CACHE->set($password => $user);
		return '';
	}
	
	my ($ok) = $dbh->do(sprintf(
		"DELETE FROM OTP WHERE User=%s AND OTP=%s",
		$dbh->quote($user),
		$dbh->quote($password),
	));
	return ($dbh->errstr) if $dbh->errstr;
	return ("Unknown user") unless $ok > 0;
	$CACHE->set($password => $user);
	return '';
}

1;


More information about the Melbourne-pm mailing list