Liz::Authenticate - generic module for Apache access authentication
<Directory /export/home/local/www/intranet> AuthName xxLINK Intranet AuthType Basic PerlAuthenHandler xxLINK::Intranet Require valid-user </Directory>
sub Intranet { Liz::Authenticate::handler( @_ ) }
or:
<Directory /export/home/local/www/liz> AuthName Private Liz AuthType Basic PerlAuthenHandler xxLINK::Liz Require valid-user </Directory>
sub Liz { Liz::Authenticate::handler( shift,\&handlerLiz ) }
sub handlerLiz {
my( $user,$password,$filename ) = @_;
return 'Not Liz' if $user ne 'liz';
return 'Not really Liz' if $password ne 'zippo';
}
The Liz::Authenticate module allows for configurable HTTP basic authentication using Liz::SQL compatible databases or any other storage of authentication data.
When using it together with Liz::SQL compatible databases, it provides a basic interface for keeping a user name, password, text info, numerical ID and options with an authentication record.
The module provides a number of primitives that can be further customised for any need necessary, or it can be used with the standard ``subscriber.lp'' Liz::Perl maintenance script.
The Liz::Authenticate module is almost never called directly. Instead, a call to the Liz::Authenticate module is embedded in a subroutine of a client module, which provides certain types of information with regards to the configuration. This subroutine is referenced in the Apache server configuration (handler).
By specifying a reference to a subroutine, it is possible to completely create your authentication method. This subroutine should expect to receive three parameters: the user name, the password specified and the filename for which authentication is needed. It should return an empty string if the authentication is successful, or a string filled with the reaseon for denial of access. Whatever happens inside that subroutine, is entirely up to the developer. For more info, see handler.
If no authentication subroutine is specified, then standard authentication is used. This uses the name of the subroutine from which Liz::Authenticate is called as the name a Liz::SQL table to check for authentication information. Most of this module's methods and subroutines apply to using this mode of authentication.
It is optionally possible to restrict users to private subdirectories within the secured directory tree. Any attempt of a user to access a file from an other user's private directory, will cause an automatic redirect of the user to their own directory. See handler for more information.
Initialization and storage of authentication information is entirely up to the developer if a custom authentication routine is used.
If standard authentication is used, any SuperUser Access will automatically create the necessary Liz::SQL compatible
table(s) that are needed.
Passwords in the Liz::Authenticate module are by default encrypted with the Liz::Password routine. For each client package that uses the Liz::Authenticate module it is possible to specify your own routine that performs the password encryption.
Whenever an authentication must be done, the package for which autentication is to be done, is checked for the existence of the routine ``Password''. If it exists, it is expected to receive the uncrypted password and return the the crypted version of the password. For example:
sub Password { crypt(shift,'xx') }
Please note that it is very unwise to change the method of password encryption after user records have already been entered, because the existing crypted password will never match using the new encryption method.
For each client package that uses the Liz::Authenticate module it is possible to specify your own superuser name and password that supercedes the default superuser name and password.
Whenever an authentication must be done, the package for which autentication is to be done, is checked for the existence of the routine ``SuperUser''. If it exists, it is expected to return two parameters: the superuser name and the crypted version of the password to check against. For example:
sub SuperUser { 'superusername','0980hjlkbkjkty' ) }
Please note that the password string must be returned in crypted format. This is done to prevent anybody with read access to the Perl module to also gain access to the superuser access immediately also.
The basic functionality of the Liz::Authenicate module is to act as a ModPerl Authenticate Handler (PerlAuthenHandler).
Generic Authentication handler for use within client modules. A client (sub)module should supply the routine ``handler'' which in turn calls the handler routine in this package, passing the reference of a routine that does the actual check.
If no handler is given, check an xxAS compatible table as specified by the calling subroutine.
1 reference to routine that does the actual check or package::table specification
(default: use callers package to create new object, use caller's
subroutine as name of table to query and look for fields
"username" and "password")
2 relative directory to which the user should be limited
(default: no limitation; otherwise directory, should be specified relative
to the DOCUMENT_ROOT, with the string '$user' as indicator
of the directory name to limit to, e.g. '/private/$user'.)
1 action to be performed by Apache
The check routine should expect three input parameters: the username to check, the password given by the user and the name of the file for which access should be checked. It is expected to return the reason for denial of access (as a string) or to return undef if access should be granted.
The environment variable $ENV{'REMOTE_USER_ID'} will be set with the value of the field ``userID'' in the table if the user is authenticated and allowed access. This is usually the ID of a contact in an OCASet, which allows quick retrieval of any extra information of the user.
If more than one record in the table matches the username, then the userID's will be joined by comma's in the environment variable $ENV{'REMOTE_USER_ID'}.
Using the default access check handler of Liz::Authenticate and no user restriction to a specific directory.
in Apache server configuration:
<Directory /export/home/local/www/intranet> AuthName xxLINK Intranet AuthType Basic PerlAuthenHandler xxLINK::Intranet Require valid-user </Directory>
in xxLINK.pm:
sub Intranet { Liz::Authenticate::handler( shift ) }
Same as above, but now with an access restriction of users to subdirectories of '/private':
in xxLINK.pm:
sub Intranet { Liz::Authenticate::handler( shift,'','/private/$user' ) }
Using a custom access check routine.
in Apache server configuration:
<Directory /export/home/local/www/liz> AuthName Private Liz AuthType Basic PerlAuthenHandler Client::Access Require valid-user </Directory>
in Client.pm:
sub Access { Liz::Authenticate::handler( shift,\&_Access )
sub _Access {
# Obtain the parameters
# Allow access if it is a graphics file
# Disallow access if wrong user
# Disallow access if wrong password
my( $user,$password,$filename ) = @_;
return if $filename =~ m#\.(gif|jpe?g|png|bmp)$#io );
return 'Not client' if $user ne 'client';
return 'Not really client' if $password ne 'zippo';
}
}
Note here that the access routine is embedded within the actual handler to prevent it from being called elsewhere.
Same as above, but now with a specific user restriction to subdirectories of '/member'.
in Client.pm, Access changed to:
sub Access { Liz::Authenticate::handler( shift,\&_Access,'/member/$user' )
Create a Liz::Authenticate object for external usage.
1 package::table for which to create object
1 instantiated Liz::Authenticate object
$access = Liz::Authenticate->new( 'Recron::MemberAccess' );
The following subrouutines and methods are intended as an upgrade solution to the old PHP-based xxLink Authoring System (xxAS). The xxAS system used one database with a table for each different client authentication need.
In the Liz/ModPerl environment and its persistent database connections, it makes much more sense to put access tables in the client database, thus allowing access to the same database for user access authentication as well as other things in that client database on the same persistent database connection.
This subroutine performs the standard xxAS authentication for a given user name, password, package and identification name. It should only be called in those situations where a ``normal'' xxAS authentication is not enough, but it is still handy to use the standard xxAS authentication structure (as opposed to devising a completely new authentication method).
1 user name 2 password 3 package name::identification name
1 reason for failed authentication (undef: authenticated ok) 2 object with which xxAS compatible authentication was performed
Configuration in httpd.conf:
PerlAuthenHandler Client::MemberAccess
In Client.pm:
sub MemberAccess {
Liz::Authenticate->handler( shift,\&ZipDirCheck );
sub ZipDirCheck {
# Obtain the parameters # Do "normal" xxAS authentication # Return with error if there is a reason to fail # Return it's ok if we don't need to do an extra check
my ($user,$password,$filename) = @_;
my ($reason,$object) =
Liz::Authenticate::xxAS( $user,$password,'Client::MemberAccess' );
return $reason if $reason;
return unless $filename =~ m#/zip/#i;
# Obtain the extra info of the user # Return with error if the right option is not set # Return indicating ok
my ($info,$options) = $object->UserInfo( $user );
return "Sorry, no zip directory access for $info" if $options =~ m#1#;
return;
}
}
This subroutine returns the Liz::SQL object that was used for the last xxAS compatible authentication.
1 the last Liz::Authenticate object
($info,$options,$ID,$maintainer) = Liz::Authenticate::Object->UserInfo;
if( $maintainer ) {
print "allow extra options for maintainers\n";
}
Return the name of the package for which standard authentication is being performed.
1 the package for which we're authenticating
<PRINT "join( '::',Liz::Authenticate::Object->Get( qw(Package Table) ) )">
Return the name of the table token for which standard authentication is being performed.
1 the table token for which we're authenticating
<PRINT "join( '::',Liz::Authenticate::Object->Get( qw(Package Table) ) )">
Return the number of users that are currently available.
1 the number of users in the table
$users = Liz::Authenticate::Object->Count;
Return a list of users in the indicated xxAS compatible database matching the optionally specified wildcard and/or numeric limitation.
1 name of table to be checked
(default: field "TABLE")
2 additional query to be performed
(default: none)
3 ordinal number of first user to be returned
(default: 1 )
4 number of users to be returned
(default: rest)
5 return users in form "username\tuserID"
(default: just return user name)
1..N the names of the users that matched
Convert a userID to a username\tuserID combination that can be used to obtain information from. Usually needed for being able to link an OCASet::Contact to a Liz::Authenticate user.
1 userID to search name for 2 name of table to be checked (default: field "TABLE" in object)
1 username\tuserID string (undef if not found)
$user = $object->UserID2Name( $ID ) if $ID;
Returns the user info of the current user after a successful xxAS compatible authentication when called as a subroutine. Handy for doing additional checks on the user.
Sets or returns the user info of a particular user in an xxAS compatible table when called as a method.
1 name of user to be checked (default: current user, can be specified as a "username\tuserID" pair) 2 name of table to be checked (default: field "TABLE" in object) 3 new extra information (default: no change) 4 new options (default: no change) 5 new password (default: no change) 6 new userID (default: no change)
1 current/old extra information 2 current/old options 3 current/old userID 4 current maintainer flag
($info,$options,$ID,$maintainer) = Liz::Authenticate::UserInfo;
or:
$object = Liz::Authenticate::Object; ($info,$options,$ID,$maintainer) = $object->UserInfo( $user );
Add a new user to the indicated table with the specified information.
1 name of user to be added 2 name of table in which to add user (default: field "TABLE" in object) 3 information associated with user (default: none) 4 options associated with user (default: none) 5 password of user (default: none) 6 userID of user (default: 0)
$object = Liz::Authenticate::Object;
$object->UserAdd( $username,'',$info );
if( $error = $object->Error ) {
print "Error: $error\n";
}
Deletes the indicated user from the indicated xxAS compatible table.
1 name of user to be deleted (can be specified as a "username\tuserID" pair) 2 name of table to be checked (default: field "TABLE" in object)
$object = Liz::Authenticate::Object; $object->UserDelete( $user );
Returns the number of indicated users that exist in the indicated xxAS compatible table. Can be either 0 (none), 1 or more than one if only a user name is checked and multiple user names with different userID's exist in the table.
1 name of user to be checked (can be specified as a "username\tuserID" pair) 2 name of table to be checked (default: field "TABLE" in object)
1 number of users matching the name and optionally ID
$object = Liz::Authenticate::Object; print "User $user exists\n" if $object->UserExists( $user );
Elizabeth Mattijsen ( lizperl@INC.nl )
(C) 1998-2000 International Network Consultants
Added extra handling in handler of cases in which the protection is not set to OK already: specifically for URL with directory names and no trailing slash.
Put module name between quotes to fix obscure bug in Perl 5.005x under ModPerl in method xxAS.
Adapted method handler to use the new xxAS subroutine.
Added new subroutine xxAS to perform xxAS style authentication.
Changed to new source typography.
Now no longer puts Exporter in ISA: it is not needed.
Added check for the validity of the request object in handler.
Fixed problem in handler which would cause an internal server error if the table did not exist.
Changed CREATE TABLE in method handler to use the new Liz::SQL 'create' method.
Changed from using method ``Exists'' to ``Count'' in method handler to check whether a table exists, which is much faster.
Added quite some general documentation under the DESCRIPTION header.
Added method UserID2Name which converts a userID to a username\tuserID combination. Needed for those situation where only the userID is known.
It is now possible to specify a method of password encryption for each package that uses the Liz::Authenticate module.
The previously undocumented SUPERDUPER feature, has now been changed to ``SuperUser'' and can be customised for each package that makes use of the Liz::Authenticate module.
Method Users now allows specification of a flag to return usernames with userIDs in a TAB-delimited format (``username\tuserID'').
Methods UserDelete and UserExists now allow the username to be specified as a string containing the username and userID, seperated by a TAB delimiter (``username\tuserID'').
Support added for multiple usernames with different userID's and different passwords.
Changed table definition to that multiple email addresses are allowed as long as the associated userID is different. This should not matter with older tables, so that a database version change is not needed.
Changed second parameter of method Users to ``additional query'' to allow for more flexibility.
Added method Count as a local method, because the inherited method looked at the wrong table.
Fixed problem with images that were redirected for maintainers.
Method UserExists added: allows simple checking whether a particular user exists.
Method new added: allows external access to tables.
Methods Package and Table added for obtaining information for which we are authenticating.
Now also sets field ``PACKAGE'' with the name of the package for which we are authenticating.
Fixed problem with creating new tables.
Added support for generic Package::Table specification and the option to limit the user to a specific directory in method handler.
Added more configuration examples to method handler.
Support for userID added.
Probably fixed problem with the Object subroutine also, by always fully qualifying $Liz::Authenticate::OBJECT.
Reduced memory footprint by using fully qualified global variables.
New method/subroutine Object added: returns the object created with the xxAS compatible authentication.
New method Users added: obtain complete or partial listing of users in an xxAS compatible table.
New method UserInfo added: obtain or change information in a xxAS compatible table. Can also be called as a subroutine: then only returns information of the current user.
New method UserAdd added: add a named user to the indicated table.
New method UserDelete added: delete a named user from the indicated table.
Auto-creation of xxAS compatible table added if the super user.
Documentation extended.
The filename for which access should be checked, is now also passed to the handler routine of Client library.
The default handler now always allows access to files with the extension .gif, .jpg, .jpeg, .png and .bmp. Since graphics are usualy not that important on a protected site, it does not really make sense to check access for every little button on a grpahics intensive site. This should reduce the number of database connections needed significantly.
First version of this true Perl module.