Problem with Apache2::AuthCookie and Apache 2.4: "failed to resolve handler"

Brian Candler <[email protected]>
Newsgroups gmane.comp.apache.mod-perl
Message-ID <[email protected]>
I have code which works with apache 2.2 but not apache 2.4, and I have 
boiled this down to a simple reproducing test case.

It works with: Ubuntu 12.04 (apache 2.2.22, mod_perl 2.0.5, 
Apache2::AuthCookie 3.18)
It does not work with: Ubuntu 14.04 (apache 2.4.7, mod_perl 2.0.8, 
Apache2::AuthCookie 3.20)

The second setup gives the following in the error log:

     failed to resolve handler Example::AuthHandler

when trying to access a page under /testsite/protected/ *after* you have 
successfully logged in. If you go to /testsite/logout.html to clear the 
cookie, and then to /testsite/protected/<any>, it still displays the 
login page successfully.

The test case is so small that I've reproduced it entirely inline below. 
You can also get it as a 1.5KB tar bundle from 
https://osl.uoregon.edu/redmine/attachments/download/155/authcookiesite.tgz

I see some fairly old reports here:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=666837
https://rt.cpan.org/Public/Bug/Display.html?id=85832

however from the first link, it *looks* like all this should be working 
with Debian (and hence Ubuntu 14.04 recently derived from it).

I notice that there is a newer version of Apache2::AuthCookie (3.22) 
available, so I installed that from CPAN. But this changes the error to:

[Wed Jun 25 13:35:26.054231 2014] [perl:error] [pid 17668] [client 
10.0.2.2:50801] Can't locate object method "requires" via package 
"Apache2::RequestRec" at 
/usr/local/share/perl/5.18.2/Apache2/AuthCookie.pm line 388.\n, referer: 
http://localhost:8013/testsite/protected/example.html

and indeed, I see no 'requires' member in 
http://perl.apache.org/docs/2.0/api/Apache2/RequestRec.html

Does anybody have any clues they can pass on?

Many thanks,

Brian Candler.

(Code assumes it's unpacked under /var/tmp; if it's somewhere else then 
change the first line of testsite.conf and setup.pl as appropriate)

==> testsite.conf <==
PerlRequire /var/tmp/setup.pl
PerlModule Example::TestSite
PerlModule Example::AuthHandler
PerlSetVar TestAuthPath /testsite
PerlSetVar TestAuthLoginScript /testsite/login.html

<Location /testsite/>
   ### To recognize logged-in users even outside of protected area:
   #AuthType Example::AuthHandler
   #AuthName TestAuth
   SetHandler perl-script
   PerlResponseHandler Example::TestSite
</Location>

<Location /testsite/protected/>
   AuthType Example::AuthHandler
   AuthName TestAuth
   PerlAuthenHandler Example::AuthHandler->authenticate
   PerlAuthzHandler Example::AuthHandler->authorize
   Require valid-user
</Location>

<Location /testsite/dologin>
   AuthType Example::AuthHandler
   AuthName TestAuth
   PerlResponseHandler Example::AuthHandler->login
</Location>

<Location /testsite/logout.html>
   AuthType Example::AuthHandler
   AuthName TestAuth
</Location>


==> setup.pl <==
use lib qw(/var/tmp);
1;

==> Example/TestSite.pm <==
package Example::TestSite;
use strict;
use warnings;

use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::Const -compile => qw(OK);
use Example::AuthHandler ();

sub handler {
   my $r = shift;
   $r->content_type('text/html');
   $r->status(200);
   $r->print(<<EOS);
<html><body>
<p>
<a href="/testsite/general.html">General</a> |
<a href="/testsite/protected/example.html">Protected</a> |
<a href="/testsite/logout.html">Logout</a>
</p>
EOS
   if ($r->uri() eq '/testsite/login.html') {
     $r->print(<<EOS);
<p>Please login:</p>

<form action="/testsite/dologin" method="post">
<input type="text" name="credential_0" />
<input type="password" name="credential_1" />
<input type="hidden" name="destination" 
value="/testsite/protected/success.html" />
<input type="submit" />
</form>
EOS
   }
   elsif ($r->uri() eq '/testsite/logout.html') {
     $r->auth_type->logout($r);
     $r->print("<p>You are logged out, goodbye</p>");
   }
   else {
     $r->print("<p>Hello, uri is " . $r->uri() . "</p>\n"); # FIXME: 
escape html
     if ($r->user) {
       $r->print("<p>You are logged in as " . $r->user . "</p>\n");
     }
     else {
       Example::AuthHandler->recognize_user($r);
       if ($r->user) {
         $r->print("<p>(Not protected but I recognize you as ". $r->user 
. ")</p>\n");
       }
     }
   }
   $r->print(<<EOS);
</body></html>
EOS
   return Apache2::Const::OK;
}

1;

==> Example/AuthHandler.pm <==
package Example::AuthHandler;
use base qw(Apache2::AuthCookie);

sub authen_cred ($$\@) {
   my $self = shift;  # Package name (same as AuthName directive)
   my $r    = shift;  # Apache request object
   my @cred = @_;     # Credentials from login form

   if ($cred[0] eq 'foo' && $cred[1] eq 'bar') {
     return 'abcd1234';
   }
   return undef;
}

sub authen_ses_key ($$$) {
   my ($self, $r, $session_key) = @_;
   if ($session_key eq 'abcd1234') {
     return 'foo';
   }
   return undef;
}

1;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.