Apache-AuthCASSimple

 view release on metacpan or  search on metacpan

lib/Apache/AuthCASSimple.pm  view on Meta::CPAN

#
# handler()
#
# Called by apache/mod_perl
#
sub handler ($) {
  my $r = shift;
  my $log = $r->log();


  # does it need to do something ?
  return DECLINED unless($r->auth_type() eq __PACKAGE__);

  $log->info(__PACKAGE__.": Entering into authentification process.:".$r->uri() ."--".$r->args());

  # Get module config (Apache directive values)
  my $cfg = Apache::ModuleConfig->get($r, __PACKAGE__);


  # Check for internal session
  my $user;
  if($cfg->{_cas_session_timeout} >= 0 && ($user = _get_user_from_session($r))) {
    $log->info(__PACKAGE__.": Session found for user $user.");
    $r->connection->user($user);
    return OK;
  }
  elsif($cfg->{_cas_session_timeout} >= 0) {
    $log->info(__PACKAGE__.": No session found.");
  }
  else {
    $log->info(__PACKAGE__.": Session disabled.");
  }

  # instance CAS object
  my ($cas, %options);
  $options{casUrl} = ($cfg->{_cas_ssl} ? 'https://' : 'http://').$cfg->{_cas_name}.':'.$cfg->{_cas_port}.$cfg->{_cas_path};
 # $options{CAFile} = $cfg->{_ca_file} if ($cfg->{_cas_ssl});

  unless($cas = Authen::CAS::Client->new($options{casUrl}, fatal => 1)) {
    $log->error(__PACKAGE__.": Unable to create CAS instance.");
    return SERVER_ERROR;
  }

  my $requested_url = _get_requested_url($r,$cfg);
  my $login_url = $requested_url;
  # TODO better clean url
  $login_url =~ s/\?/\&/;
  $login_url = $cas->login_url().$login_url;

  # redirect to CAS server unless ticket parameter
  my %args = $r->args();
  unless ($args{ticket}) {
    $log->info(__PACKAGE__.": No ticket, client redirected to CAS server.");
    $r->err_header_out("Location" => $login_url);
    return REDIRECT;
  }


  # Validate the ticket we received
  if ($args{ticket}=~/^PT/) {
      my $r = $cas->proxy_validate( $requested_url, $args{ticket} );
        if( $r->is_success() ) {
            $user=$r->user();
            $log->warn(__PACKAGE__.": Validate PT on CAS Proxy server. ".join ",", $r->proxies());
        };
  }
  else {
      my $r = $cas->service_validate( $requested_url, $args{ticket} );
      if ( $r->is_success() ) {
        $user = $r->user();
      }
  }

  unless ($user) {
    $log->warn(__PACKAGE__.": Unable to validate ticket ".$args{ticket}." on CAS server.");
    $r->err_header_out("Location" => $login_url);
    return REDIRECT;
    #return FORBIDDEN;
  }

  $log->info(__PACKAGE__.": Ticket ".$args{ticket}." succesfully validated.");

  if ( $user ) {
   $r->connection->user($user);

   $log->info(__PACKAGE__.": New session ".$r->uri() ."--".$r->args());

   # if we are there (and timeout is set), we can create session data and cookie
   _remove_ticket($r);
   _create_user_session($r) if($cfg->{_cas_session_timeout} >= 0);
   $r->err_header_out("Location" => $r->uri . ($r->args ? '?' . $r->args : '') );
   # if session, redirect remove ticket in url
   return ($cfg->{_cas_session_timeout}  >= 0)?REDIRECT:OK;
  }

  return FORBIDDEN;

}

#
# _get_requested_url()
#
# Return the URL requested by client (with args)
#
sub _get_requested_url ($$) {
  my $r = shift;
  my $cfg = shift;

  my $port = $r->get_server_port();
  my $is_https = $r->subprocess_env('https') ? 1 : 0;

  my $url = $is_https ? 'https://' : 'http://';
  $url .= $r->hostname();
  $url .= ':'.$port if (!$cfg->{_mod_proxy} && ( ($is_https && $port != 443) || (!$is_https && $port != 80) ));
  $url .= $r->uri()._get_query_string($r);

  return $url;
}

#
# _get_query_string()
#
# Return the query string
#
sub _get_query_string ($) {
  my $r = shift;

  _post_to_get($r) if ($r->method eq 'POST');

  my %args = $r->args();
  my @qs = ();

  foreach (sort {$a cmp $b} keys(%args)) {
    next if ($_ eq 'ticket');
    push(@qs, $_."=".$args{$_});
  }

  return $#qs != -1 ? "?".join("\&", @qs) : "";
}

#



( run in 1.256 second using v1.01-cache-2.11-cpan-140bd7fdf52 )