Updating Distauth modules to support form-based authentication
These notes are based on my modifications to the UNIX Apache2 Distauth.pm module.
New config variables:
-
authenticator_url - There is now an additional possible value for the authenticator_url variable:
https://secureWeb.ucdavis.edu/form-auth/sendback
To match authenticator_url against /form-auth/ to set a $form_auth variable, which is used later to decide whether we need to test the DA1 cookie:
my $form_auth = ($redirect_to =~ /form-auth/) ? 1 : 0; -
logout_interval - This contains the number of seconds before the user will be forced to login again. The cookie
itself expires after 12 hours. Example:
my $logoutinterval = $r->dir_config('logout_interval') || 43200;
Testing the DA1 Cookie
If $form_auth is 1, we just need to make sure the DA1 cookie is valid and the logout
interval has not yet passed. If the cookie does not exist, send the user back to get
one. If it does but has expired, send them to the logout URL so the cookie can be destroyed
and the user can login again:
if($form_auth) {
my $da1cookie = get_da1_cookie($r);
my ($authtime, $authmethod) = parse_da1_cookie($da1cookie);
# Check for existence and format of cookie
if(!$authtime || !$authmethod) {
$r->log_reason("Distauth form cookie does not exist", $r->filename );
return go_get_a_cookie($r, $redirect_to);
}
# Check for timeout
my $now = time();
if((time() - $authtime) > $logoutinterval) {
$r->log_reason("Distauth form cookie with timestamp $authtime has expired by $now (interval: $logoutinterval) ", $r->filename);
return logout($r, $redirect_to);
}
}
Functions used by the above:
sub parse_da1_cookie {
my $cookievalue = shift;
# time, method
my ($a, $b) = ($cookievalue =~ /DA1=(\w+)-(\w+)/);
return ($a, $b);
}
sub get_da1_cookie {
my $r = shift;
my %cookies = CGI::Cookie->parse($r->header_in('Cookie'));
return $cookies{"DA1"};
}
sub logout {
my ($r, $redirect_to) = @_;
my $redirect_logout = "https://secureWeb.ucdavis.edu/form-auth/logout";
my $query = $r->parsed_uri->query;
my $http = $r->dir_config("http_prefix") ||
(($r->get_server_port =~ /\d?443/)?"https":"http");
$redirect_logout .= "?$http://" . $r->headers_in->{'Host'} . $r->uri();
$redirect_logout .= "?$query" if ($query);
$r->header_out(Location => $redirect_logout);
$r->custom_response($Apache::Constants::REDIRECT,"<h1>You need to Authenticate</h1><p>Please go $redirect_to to properly authenticate to this Web page.\n");
return REDIRECT;
}
