Distauth: Apache Form-Based Notes

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:

  1. 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;
  2. 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;
}