Apache-AuthDigest

 view release on metacpan or  search on metacpan

API/API.pm  view on Meta::CPAN

  return AUTH_REQUIRED;

=item compare_digest_response()

this method represents a shortcut for comparing a client Digest
request with whatever credentials are stored on the server.  the
first argument is the hash reference returned by 
get_digest_auth_response().  the second argument is a MD5 digest
of the user credentials.  the credentials should be in the form

  user:realm:password 

before they are hashed.  the following Perl one-liner will generate
a suitable digest:

  $ perl -MDigest::MD5 -e'print Digest::MD5::md5_hex("user:realm:password"),"\n"'

=back

=head1 EXAMPLE

for a complete example, see the My/DigestAuthenticator.pm file
in the test suite for this package, as well as AuthDigest.pm.
In general, the steps are the same as for Basic authentication, 
examples of which abound on CPAN, the Eagle book, and the Cookbook:

AuthDigest.pm  view on Meta::CPAN


    return DECLINED;
  }

  my $cfg = Apache::ModuleConfig->get($r, __PACKAGE__);

  my ($status, $response) = $r->get_digest_auth_response;

  return $status unless $status == OK;

  my $password_file = $cfg->{_password_file};

  my $fh = Apache::File->new($password_file);

  unless ($fh) {
    $log->error("Apache::AuthDigest - could not open ",
                 "password file '$password_file'");

    return DECLINED;
  }

  my $digest = get_user_credentials($r->user, $r->auth_name, $fh);

  unless ($digest) {
    $log->error("Apache::AuthDigest - user '", $r->user,
                "' not found in password file '$password_file'");

    $r->note_digest_auth_failure;
    return AUTH_REQUIRED;
  }

  return OK if $r->compare_digest_response($response, $digest);

  $log->error("Apache::AuthDigest - user '", $r->user,
              "' password mismatch");

  $r->note_digest_auth_failure;
  return AUTH_REQUIRED;
}

sub get_user_credentials {

  my ($user, $realm, $fh) = @_;

  my ($username, $userrealm, $digest) = ();

AuthDigest.pm  view on Meta::CPAN



sub AuthDigestFile ($$$) {

  my ($cfg, $parms, $arg) = @_;

  return DECLINE_CMD if Apache->module('mod_digest.c');

  die "Invalid AuthDigestFile $arg!" unless -f $arg;

  $cfg->{_password_file}  = $arg;
}

sub DIR_CREATE {
  # Initialize an object instead of using the mod_perl default.

  my $class = shift;
  my $self  = { _password_file => undef };

  return bless $self, $class;
}

sub DIR_MERGE {
  # Allow the subdirectory to inherit the configuration
  # of the parent, while overriding with anything more specific.

  my ($parent, $current) = @_;

Changes  view on Meta::CPAN

Revision history for Perl extension Apache::DigestAPI

0.01  09.06.2002
	- original version
          lots of feeback from Andrew Ho

0.02  09.06.2002
        - fixed bug in AuthDigest.pm where the last
          digest in the password file was returned if
          no user is found

        - fixed AuthDigestFile so that AuthDigest.pm
          actually works, as do the tests (note to
          self: run test suite both with and without
          mod_digest compiled in httpd)

        - minor tweak to (nonpublic) parse_digest_header()

        - never release on friday, especially friday

MANIFEST  view on Meta::CPAN

t/05session.t
t/06parse.t
t/07multi.t
t/99pod.t
t/lib/perl/My/MultiAuthenticator.pm
t/lib/perl/My/DigestAuthenticator.pm
t/lib/perl/My/SessionAuthenticator.pm
t/lib/perl/My/SessionAuthorizor.pm
t/lib/perl/My/SessionGenerator.pm
t/conf/extra.conf.in
t/conf/password_file
contrib/AuthDigestDBI.pm
contrib/README

Makefile.PL  view on Meta::CPAN


use ExtUtils::MakeMaker;
use Apache::ExtUtils qw(command_table);
use Apache::src ();
use Config;

use strict;

my @directives = (
  { name         => 'AuthDigestFile',
    errmsg       => 'text file containing user IDs and passwords',
    args_how     => 'TAKE1',
    req_override => 'OR_AUTHCFG', },
);

command_table(\@directives);

my %config;

$config{INC} = Apache::src->new->inc;

contrib/AuthDigestDBI.pm  view on Meta::CPAN

# 1: report about cache miss
# 2: full debug output
$Apache::AuthDigestDBI::DEBUG = 0;


# configuration attributes, defaults will be overwritten with values from .htaccess.

my %Config = (
    'Auth_DBI_data_source'      => '',
    'Auth_DBI_username'         => '',
    'Auth_DBI_password'         => '',
    'Auth_DBI_pwd_table'        => '',
    'Auth_DBI_uid_field'        => '',
    'Auth_DBI_pwd_field'        => '',
    'Auth_DBI_pwd_whereclause'  => '',
    'Auth_DBI_grp_table'        => '',
    'Auth_DBI_grp_field'        => '',
    'Auth_DBI_grp_whereclause'  => '',
    'Auth_DBI_log_field'        => '',
    'Auth_DBI_log_string'       => '',
    'Auth_DBI_authoritative'    => 'on',
    'Auth_DBI_nopasswd'         => 'off',
    'Auth_DBI_encrypted'        => 'on',
    'Auth_DBI_encryption_salt'  => 'password',
    'Auth_DBI_uidcasesensitive' => 'on',
    'Auth_DBI_pwdcasesensitive' => 'on',
    'Auth_DBI_placeholder'      => 'off',
);

# stores the configuration of current URL.
# initialized  during authentication, eventually re-used for authorization.
my $Attr = { };


# global cache: all records are put into one string.
# record separator is a newline. Field separator is $;.
# every record is a list of id, time of last access, password, groups (authorization only).
# the id is a comma separated list of user_id, data_source, pwd_table, uid_field.
# the first record is a timestamp, which indicates the last run of the CleanupHandler followed by the child counter.

my $Cache = time . "$;0\n";

# unique id which serves as key in $Cache.
# the id is generated during authentication and re-used for authorization.
my $ID;


contrib/AuthDigestDBI.pm  view on Meta::CPAN

        $type .= 'main'     if $r->is_main;
        print STDERR "==========\n$prefix request type = >$type< \n";
    }

    return OK unless $r->is_initial_req; # only the first internal request

    print STDERR "REQUEST:\n", $r->as_string if $Apache::AuthDigestDBI::DEBUG > 1;
	
	my $auth = 'digest';

	# here the dialog pops up and asks you for username and password
	my ($status, $response, $res, $passwd_sent);
	if ($r->header_in("Authorization") =~ /^Basic (.*)/i) {
		$auth = 'Basic';
		my $username;
		($username, $passwd_sent) = split ':', old_decode_base64($1);
		$r->connection->user($username);
	}

	if ($auth eq 'digest') {

		$r = Apache::AuthDigest::API->new($r);
		($status, $response) = $r->get_digest_auth_response;		
		return $status unless $status == OK;
		$passwd_sent = 'digest';
		
	} else {
	
		#($res, $passwd_sent) = $r->get_basic_auth_pw;
		#print STDERR "$prefix get_basic_auth_pw: res = >$res<, password sent = >$passwd_sent<\n" if $Apache::AuthDigestDBI::DEBUG > 1;
		#return $res if $res; # e.g. HTTP_UNAUTHORIZED
		
		return AUTH_REQUIRED unless $passwd_sent;
		
	}

    # get username
    my ($user_sent) = $r->connection->user;
    print STDERR "$prefix user sent = >$user_sent<\n" if $Apache::AuthDigestDBI::DEBUG > 1;

contrib/AuthDigestDBI.pm  view on Meta::CPAN

    while(($key, $val) = each %Config) {
        $val = $r->dir_config($key) || $val;
        $key =~ s/^Auth_DBI_//;
        $Attr->{$key} = $val;
        printf STDERR "$prefix Config{ %-16s } = %s\n", $key, $val if $Apache::AuthDigestDBI::DEBUG > 1;
    }

    # parse connect attributes, which may be tilde separated lists
    my @data_sources = split(/~/, $Attr->{data_source});
    my @usernames    = split(/~/, $Attr->{username});
    my @passwords    = split(/~/, $Attr->{password});
    $data_sources[0] = '' unless $data_sources[0]; # use ENV{DBI_DSN} if not defined

    # obtain the id for the cache
    my $data_src = $Attr->{data_source};
    $data_src =~ s/\(.+\)//go; # remove any embedded attributes, because of trouble with regexps
    $ID = join ',', $user_sent, $data_src, $Attr->{pwd_table}, $Attr->{uid_field};

    # if not configured decline
    unless ($Attr->{pwd_table} && $Attr->{uid_field} && $Attr->{pwd_field}) {
        printf STDERR "$prefix not configured, return DECLINED\n" if $Apache::AuthDigestDBI::DEBUG > 1;
        return DECLINED;
    }

    # do we want Windows-like case-insensitivity?
    $user_sent   = lc($user_sent)   if $Attr->{uidcasesensitive} eq "off";
    $passwd_sent = lc($passwd_sent) if $Attr->{pwdcasesensitive} eq "off";

    # check whether the user is cached but consider that the password possibly has changed
    my $passwd = '';
    my $salt   = '';
    if ($CacheTime) { # do we use the cache ?
        if ($SHMID) { # do we keep the cache in shared memory ?
            semop($SEMID, $obtain_lock) or print STDERR "$prefix semop failed \n";
            shmread($SHMID, $Cache, 0, $SHMSIZE) or printf STDERR "$prefix shmread failed \n";
            substr($Cache, index($Cache, "\0")) = '';
            semop($SEMID, $release_lock) or print STDERR "$prefix semop failed \n";
        }
        # find id in cache

contrib/AuthDigestDBI.pm  view on Meta::CPAN

            $passwd_cached = $2;
            $groups_cached = $3;
            printf STDERR "$prefix cache: found >$ID< >$last_access< >$passwd_cached< \n" if $Apache::AuthDigestDBI::DEBUG > 1;
			if ($auth eq 'digest') {
				$salt = $response->{'realm'};
				my $passwd_to_check = Digest::MD5::md5_hex(join ':', $user_sent, $salt, $passwd_cached);
				$passwd = $passwd_cached if $r->compare_digest_response($response, $passwd_to_check);
			} else {
				$salt = $Attr->{encryption_salt} eq 'userid' ? $user_sent : $passwd_cached;
				my $passwd_to_check = $Attr->{encrypted} eq 'on' ? crypt($passwd_sent, $salt) : $passwd_sent; 
				# match cached password with password sent 
				$passwd = $passwd_cached if $passwd_to_check eq $passwd_cached;
			}
        }
    }

    if ($passwd) { # found in cache
        printf STDERR "$prefix passwd found in cache \n" if $Apache::AuthDigestDBI::DEBUG > 1;
    } else { # password not cached or changed
        printf STDERR "$prefix passwd not found in cache \n" if $Apache::AuthDigestDBI::DEBUG;

        # connect to database, use all data_sources until the connect succeeds
        my $j;
        for ($j = 0; $j <= $#data_sources; $j++) {
            last if ($dbh = DBI->connect($data_sources[$j], $usernames[$j], $passwords[$j]));
        }
        unless ($dbh) {
            $r->log_reason("$prefix db connect error with data_source >$Attr->{data_source}<", $r->uri);
            return SERVER_ERROR;
        }

        # generate statement
        my $user_sent_quoted = $dbh->quote($user_sent);
        my $select    = "SELECT $Attr->{pwd_field}";
        my $from      = "FROM $Attr->{pwd_table}";

contrib/AuthDigestDBI.pm  view on Meta::CPAN


        # fetch result
        while ($_ = $sth->fetchrow_array) {
            # strip trailing blanks for fixed-length data-type
            $_ =~ s/ +$// if $_;
            # consider the case with many users sharing the same userid
	    $passwd .= "$_$;";
        }

        chop  $passwd if $passwd;
        undef $passwd if 0 == $sth->rows; # so we can distinguish later on between no password and empty password

        if ($sth->err) {
            $dbh->disconnect;
            return SERVER_ERROR;
        }
        $sth->finish;

        # re-use dbh for logging option below
        $dbh->disconnect unless ($Attr->{log_field} && $Attr->{log_string});
    }

    $r->subprocess_env(REMOTE_PASSWORDS => $passwd);
    print STDERR "$prefix passwd = >$passwd<\n" if $Apache::AuthDigestDBI::DEBUG > 1;

    # check if password is needed
    if (!defined($passwd)) { # not found in database
        # if authoritative insist that user is in database
        if ($Attr->{authoritative} eq 'on') {
            $r->log_reason("$prefix password for user $user_sent not found", $r->uri);
            $r->note_basic_auth_failure;
            return AUTH_REQUIRED;
        } else {
            # else pass control to the next authentication module
            return DECLINED;
        }
    }

    # allow any password if nopasswd = on and the retrieved password is empty
    if ($Attr->{nopasswd} eq 'on' && !$passwd) {
        return OK;
    }

    # if nopasswd is off, reject user
    unless ($passwd_sent && $passwd) {
        $r->log_reason("$prefix user $user_sent: empty password(s) rejected", $r->uri);
        $r->note_basic_auth_failure;
        return AUTH_REQUIRED;
    }

    # compare passwords
    my $found = 0;
    my $password;
    foreach $password (split(/$;/, $passwd)) {
        # compare the two passwords possibly crypting the password if needed
        my $did_match = 0;
		if ($auth eq 'digest') {
			$salt = $response->{'realm'};
			# password to check is in a reverse role from below
			# it's the correct password
			my $passwd_to_check = Digest::MD5::md5_hex(join ':', $user_sent, $salt, $password);
			$did_match = 1 if $r->compare_digest_response($response, $passwd_to_check);
		} else {
			$salt = $Attr->{encryption_salt} eq 'userid' ? $user_sent : $password;
			my $passwd_to_check = $Attr->{encrypted} eq 'on' ? crypt($passwd_sent, $password) : $passwd_sent;
            print STDERR "$prefix user $user_sent: > '$passwd_to_check' eq '$password' < \n" if $Apache::AuthDigestDBI::DEBUG > 1;
			$did_match = 1 if $passwd_to_check eq $password;
		}
		
        if ($did_match) {
            $found = 1;
            $r->subprocess_env(REMOTE_PASSWORD => $password);
            print STDERR "$prefix user $user_sent: password match for >$password< \n" if $Apache::AuthDigestDBI::DEBUG > 1;
            # update timestamp and cache userid/password if CacheTime is configured
            if ($CacheTime) { # do we use the cache ?
                if ($SHMID) { # do we keep the cache in shared memory ?
                    semop($SEMID, $obtain_lock) or print STDERR "$prefix semop failed \n";
                    shmread($SHMID, $Cache, 0, $SHMSIZE) or printf STDERR "$prefix shmread failed \n";
                    substr($Cache, index($Cache, "\0")) = '';
                }
                # update timestamp and password or append new record
                my $now = time;
                if (!($Cache =~ s/$ID$;\d+$;.*$;(.*)\n/$ID$;$now$;$password$;$1\n/)) {
		    $Cache .= "$ID$;$now$;$password$;\n";
                } else {
                }
                if ($SHMID) { # write cache to shared memory
                    shmwrite($SHMID, $Cache, 0, $SHMSIZE)  or printf STDERR "$prefix shmwrite failed \n";
                    semop($SEMID, $release_lock) or print STDERR "$prefix semop failed \n";
                }
            }
            last;
        }
    }
    unless ($found) {
        $r->log_reason("$prefix user $user_sent: password mismatch", $r->uri);
		if ($auth eq 'digest') {
			$r->note_digest_auth_failure;
		} else {
			$r->note_basic_auth_failure;		
		}
        return AUTH_REQUIRED;
    }

    # logging option
    if ($Attr->{log_field} && $Attr->{log_string}) {
        if (!$dbh) { # connect to database if not already done
            my ($j, $connect);
            for ($j = 0; $j <= $#data_sources; $j++) {
                if ($dbh = DBI->connect($data_sources[$j], $usernames[$j], $passwords[$j])) {
                    $connect = 1;
                    last;
                }
            }
            unless ($connect) {
                $r->log_reason("$prefix db connect error with $Attr->{data_source}", $r->uri);
                return SERVER_ERROR;
            }
        }
        my $user_sent_quoted = $dbh->quote($user_sent);

contrib/AuthDigestDBI.pm  view on Meta::CPAN


    # get username
    my ($user_sent) = $r->connection->user;
    print STDERR "$prefix user sent = >$user_sent<\n" if $Apache::AuthDigestDBI::DEBUG > 1 ;

    # here we could read the configuration, but we re-use the configuration from the authentication

    # parse connect attributes, which may be tilde separated lists
    my @data_sources = split(/~/, $Attr->{data_source});
    my @usernames    = split(/~/, $Attr->{username});
    my @passwords    = split(/~/, $Attr->{password});
    $data_sources[0] = '' unless $data_sources[0]; # use ENV{DBI_DSN} if not defined

    # if not configured decline
    unless ($Attr->{pwd_table} && $Attr->{uid_field} && $Attr->{grp_field}) {
        printf STDERR "$prefix not configured, return DECLINED\n" if $Apache::AuthDigestDBI::DEBUG > 1;
        return DECLINED;
    }

    # do we want Windows-like case-insensitivity?
    $user_sent = lc($user_sent) if $Attr->{uidcasesensitive} eq "off";

contrib/AuthDigestDBI.pm  view on Meta::CPAN

        }

        if ($groups) { # found in cache
            printf STDERR "$prefix groups found in cache \n" if $Apache::AuthDigestDBI::DEBUG > 1;
        } else { # groups not cached or changed
            printf STDERR "$prefix groups not found in cache \n" if $Apache::AuthDigestDBI::DEBUG;

            # connect to database, use all data_sources until the connect succeeds
            my ($j, $connect);
            for ($j = 0; $j <= $#data_sources; $j++) {
                if ($dbh = DBI->connect($data_sources[$j], $usernames[$j], $passwords[$j])) {
                    $connect = 1;
                    last;
                }
            }
            unless ($connect) {
                $r->log_reason("$prefix db connect error with $Attr->{data_source}", $r->uri);
                return SERVER_ERROR;
            }

            # generate statement

contrib/AuthDigestDBI.pm  view on Meta::CPAN

 # Authentication and Authorization in .htaccess:

 AuthName DBI
 AuthType Digest

 PerlAuthenHandler Apache::AuthDigestDBI::authen
 PerlAuthzHandler  Apache::AuthDigestDBI::authz

 PerlSetVar Auth_DBI_data_source   dbi:driver:dsn
 PerlSetVar Auth_DBI_username      db_username
 PerlSetVar Auth_DBI_password      db_password
 #DBI->connect($data_source, $username, $password)

 PerlSetVar Auth_DBI_pwd_table     users
 PerlSetVar Auth_DBI_uid_field     username
 PerlSetVar Auth_DBI_pwd_field     password
 # authentication: SELECT pwd_field FROM pwd_table WHERE uid_field=$user
 PerlSetVar Auth_DBI_grp_field     groupname
 # authorization: SELECT grp_field FROM pwd_table WHERE uid_field=$user

 require valid-user
 require user   user_1  user_2 ...
 require group group_1 group_2 ...

The AuthType may be Digest or Basic. It will 'fallback' to Basic if the client
ignores the request for Digest authentication. The password B<must not> be encrypted
for Digest authentication and the fallback to Basic. For Basic authentication,
passwords may be encrypted.

You may use one or more valid require lines. For a single require line with the
requirement 'valid-user' or with the requirements 'user user_1 user_2 ...' it is
sufficient to use only the authentication handler.


=head1 DESCRIPTION

This is a hacked up version Apache::AuthDBI that uses Apache::AuthDigest to do
Digest authentication. Please see the docs for Apache::AuthDBI for full usage.

contrib/AuthDigestDBI.pm  view on Meta::CPAN

Note that this module requires Apache::AuthDBI and Apache::AuthDigest.


=head1 SEE ALSO

L<Apache::AuthDBI>, L<Apache::AuthDigest::API>, L<Apache>, L<mod_perl>, L<DBI>


=head1 BUGS

The password must not be encrypted for use with Digest authentication.

When Digest authentication is requested, it accepts Basic authentication. (This
isn't a bug, except that you cannot shut this behavior off.)


=head1 AUTHORS

=item *
Apache::AuthDigestDBI variation by Robert Giseburt <rob@heavyhosting.net>

t/02api.t  view on Meta::CPAN

# many kudos to LWP for supporting Digest authentication natively!

my $url = '/protected/index.html';

my $response = GET $url;

ok $response->code == 401;

ok $response->header('WWW-Authenticate') =~ m/Digest realm="cookbook"/;

$response = GET $url, username => 'geoff', password => 'geoff';

ok $response->code == 200;

$response = GET $url, username => 'geoff', password => 'badpass';

ok $response->code == 401;

t/03auth.t  view on Meta::CPAN

plan tests => 7, have_lwp;

my $url = '/dropin/index.html';

my $response = GET $url;

ok $response->code == 401;

ok $response->header('WWW-Authenticate') =~ m/Digest realm="flatfile"/;

$response = GET $url, username => 'geoff', password => 'geoff';

ok $response->code == 200;

$response = GET $url, username => 'geoff', password => 'badpass';

ok $response->code == 401;

$response = GET $url, username => 'test2', password => 'badpass';

ok $response->code == 401;

$response = GET $url, username => 'test', password => 'test';

ok $response->code == 200;

$response = GET $url, username => 'nouser', password => 'nopass';

ok $response->code == 401;

t/04authz.t  view on Meta::CPAN

plan tests => 4, have_lwp;

my $url = '/authz/index.html';

my $response = GET $url;

ok $response->code == 401;

ok $response->header('WWW-Authenticate') =~ m/Digest realm="flatfile"/;

$response = GET $url, username => 'geoff', password => 'geoff';

ok $response->code == 401;

$response = GET $url, username => 'test', password => 'test';

ok $response->code == 200;

t/05session.t  view on Meta::CPAN

plan tests => 7, have_lwp;

my $url = '/session/index.html';

my $response = GET "$url?init";

ok $response->code == 401;

ok $response->header('WWW-Authenticate') =~ m/nonce="e37f0136aa3ffaf149b351f6a4c948e9"/;

$response = GET "$url?session1", username => 'geoff', password => 'geoff';

ok $response->code == 200;

ok $response->request->header('Authorization') =~ m/nonce="43fd828731048cda3a0a050b22bed4f3"/;

$response = GET "$url?expired", username => 'geoff', password => 'geoff';

ok $response->code == 401;

$response = GET "$url?session2", username => 'newuser', password => 'newpass';

ok $response->code == 401;

ok $response->request->header('Authorization') =~ m/nonce="98432f23b96c8138c2606ef8bebc0a82"/;

t/06parse.t  view on Meta::CPAN

use warnings FATAL => 'all';

use Apache::Test;
use Apache::TestRequest;

plan tests => 4, have_lwp;

# some mod_dav URL
my $url = '/parse/EPD%20Lookup/lots%201-66,%20A-G.txt';

my $response = GET $url, username => 'geoff', password => 'geoff';

ok $response->code == 200;
ok $response->content eq q!/parse/EPD%20Lookup/lots%201-66,%20A-G.txt!;

$url = '/parse/emb=edded+stuff&other$garble';

$response = GET $url, username => 'geoff', password => 'geoff';

ok $response->code == 200;
ok $response->content eq q!/parse/emb=edded+stuff&other$garble!;

t/conf/extra.conf.in  view on Meta::CPAN

  Require valid-user
  PerlAuthenHandler My::DigestAuthenticator
</Location>

Alias /dropin @DocumentRoot@
<Location /dropin>
  AuthType Digest
  AuthName flatfile
  Require valid-user
  PerlAuthenHandler Apache::AuthDigest
  AuthDigestFile @ServerRoot@/conf/password_file
</Location>

Alias /authz @DocumentRoot@
<Location /authz>
  AuthType Digest
  AuthName flatfile
  Require user test
  PerlAuthenHandler Apache::AuthDigest
  PerlAuthzHandler Apache::AuthzDigest
  AuthDigestFile @ServerRoot@/conf/password_file
</Location>

Alias /session @DocumentRoot@
<Location /session>
  AuthType Digest
  AuthName cookbook
  Require valid-user
  PerlAuthenHandler My::SessionAuthenticator
  PerlAuthzHandler My::SessionAuthorizor
  DigestSessionKey MYSESSION

t/lib/perl/My/DigestAuthenticator.pm  view on Meta::CPAN


sub get_credentials {

  my ($user, $realm) = @_;

  # this represents a routine that fetches the Digest::MD5 hash of
  # the credentials for user $r->user at realm $r->auth_name
  
  # to generate your own credentials, use the htdigest utility
  # program that ships with Apache, or the Perl one-liner
  # $ perl -MDigest::MD5 -e'print Digest::MD5::md5_hex("user:realm:password"),"\n"'

  return '966b699e9ada71dbefb7276e0fc1aaf1';
}
1;

t/lib/perl/My/SessionAuthenticator.pm  view on Meta::CPAN


sub get_credentials {

  my ($user, $realm) = @_;

  # this represents a routine that fetches the Digest::MD5 hash of
  # the credentials for user $r->user at realm $r->auth_name
  
  # to generate your own credentials, use the htdigest utility
  # program that ships with Apache, or the Perl one-liner
  # $ perl -MDigest::MD5 -e'print Digest::MD5::md5_hex("user:realm:password"),"\n"'

  return '966b699e9ada71dbefb7276e0fc1aaf1';
}
1;



( run in 1.686 second using v1.01-cache-2.11-cpan-49f99fa48dc )