[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[EP-tech] Eprints CAS Authentification



Hello,

I have some problems in the developpement of a CAS Auth for EPrints.

My first approach was using the documentation on the page :
http://wiki.eprints.org/w/CAS

This documentation is good to start, but i have some problems finishing it.
It's not accurate enough for eprints 3.x . In fact it doesn't work if we
use it like it is explained.
the first problem i ran into was that apache did not restart after
modifying the sub current_user() routine. The $username variable isn't
defined in the line
$ldap_search_string =~ s/!!USERNAME!!/$username/g;

I resolved this problem, but then i ran into another problem, the cookie
isn't found and can't be fetched. So before using raw_cookie() i tested if
the cookie existed or not.

As for now, the CAS page is visible, when i click on Login, but i have
another problem, when the user is created in the eprints Database ( right
after CAS Auth ), the user creation
method is looping like hell, and creates a bunch of first null users, then
a bunch of users with my LDAP credentials. This is not what is expected, i
expect to see only one user created with LDAP Credentials.

On another hand, when the user is already in the database, the connection
is made with the CAS, but the users can't logout. Here is my sub
current_user() routine :

sub current_user
{
    my( $self ) = @_;
    if( $self->{offline} ) { return undef; }

    if( !defined $self->{current_user} ){
        if( $self->get_archive->get_conf( "cookie_auth" ) ){
            if ( $self->get_archive->get_conf( 'cas_auth' ) ){
                my $username;
                my $cookie_name = $self->get_archive->get_conf(
'cas_cookie_name' );
                $self->{current_user} = undef;
                if( defined $ENV{'HTTP_CAS_FILTER_USER'}){
                    $username = $ENV{'HTTP_CAS_FILTER_USER'};
                    $self->{current_user} =
EPrints::DataObj::User::user_with_username( $self, $username ); # undef si
le user n'existe pas
                }
                elsif ( defined $ENV{'HTTP_COOKIE'}) {
                    # V?rification de l'existence du cookie APACHECAS
                    my @cookie1 = split("=",$ENV{'HTTP_COOKIE'}); #cookie1
= array('APACHECAS', ticket)
                    my $ticket = $cookie1[1];
                    my $sql = "SELECT user_id FROM cas_sessions where
id='".$ticket."'";
                    my $sth = $self->get_database()->prepare( $sql );
                    $self->get_database()->execute($sth);
                    my @info = $sth->fetchrow_array();
                    #my @list = split(":",$info[0]);
                    $username = $info[0];
                    $sth->finish;
                    $self->{current_user} =
EPrints::DataObj::User::user_with_username( $self, $username ); # undef si
le user n'existe pas
                }
                else {
                    $self->{current_user} = undef;
                }

                # Create user FROM LDAP server if needed
                if (not defined $self->{current_user}) {
                    my $session = $self;
                    # Verification de l'existence des cookies
                    # Si le cookie est trouv?, on d?fini le username
                    if( defined $ENV{'HTTP_COOKIE'}){
                        my $ticket = raw_cookie('APACHECAS');
                        my $sql = "SELECT user_id FROM cas_sessions where
id='".$ticket."'";
                        my $sth = $self->get_database()->prepare( $sql );
                        $self->get_database()->execute($sth);
                        my @info = $sth->fetchrow_array();
                        $username = $info[0];
                        $sth->finish;
                        my $utilisateur =
EPrints::DataObj::User::user_with_username( $self, $username );

                        if(!defined $utilisateur && ($username != '' ||
$username != undef) ){
                            # Si l'utilisateur n'existe pas dans la bdd
eprints et que le username est bien d?fini
                            # On va le chercher dans le LDAP
                            # et l'enregistrer dans la BDD Eprints

              # R?cup?ration des parametres LDAP
                            my $ldap_host =
$session->get_archive()->get_conf('ldap_host');
                            my $ldap_version =
$session->get_archive()->get_conf('ldap_version');
                            my $ldap_bind_user =
$session->get_archive()->get_conf('ldap_bind_user');
                            my $ldap_bind_pass =
$session->get_archive()->get_conf('ldap_bind_pass');
                            my $ldap_base =
$session->get_archive()->get_conf('ldap_base');
                            my $ldap_scope =
$session->get_archive()->get_conf('ldap_scope');
                            my $ldap_search_string =
$session->get_archive()->get_conf('ldap_search_string');
                            $ldap_search_string =~ s/username/$username/g;

                            my $ldap_default_email =
$session->get_archive()->get_conf('ldap_default_email');
                            my $ldap_default_country =
$session->get_archive()->get_conf('ldap_default_country');

                            my $ldap_default_org =
$session->get_archive()->get_conf('ldap_default_org');
                            my $ldap_conforms_supann =
$session->get_archive()->get_conf('ldap_conforms_supann');

                            eval "use Net::LDAP;";
                            die "Cannot load Net::LDAP: $@" if $@;

                            # Connexion au serveur LDAP
                            my $ldap = Net::LDAP->new( $ldap_host ) or die
"$@";
                            my $mesg = $ldap->bind ( $ldap_bind_user,
password => $ldap_bind_pass, version => $ldap_version, );

                            # Recherche de l'utilisateur
                            my $result = $ldap->search(    base =>
$ldap_base, scope => $ldap_scope, filter => $ldap_search_string, );

                            # Utiliser seulement la premi?re entr?e
                            my @entries = $result->entries();
                            if (defined (my $ldap_entry = $entries[0])) {
                                # Attribuer le type de l'utilisateur
                                my $usertype = "user";
                                my $user = EPrints::DataObj::User::create(
$session, $usertype );

                                # Attribuer le nom de l'utilisateur
                                $user->set_value( "username" , $username );
                                my $name = {};
                                $name->{family} = $ldap_entry->get_value(
"sn" );
                                $name->{given} = $ldap_entry->get_value(
"givenName" );
                                $user->set_value("name", $name );

                                # Attribuer l'Email
                                my $email = defined
$ldap_entry->get_value("mail")
                                    ? $ldap_entry->get_value("mail") :
$ldap_default_email;
                                    $user->set_value("email", $email);

                                if ( $ldap_conforms_supann ){
                                    $user->set_value("org",
$ldap_entry->get_value("supannEtablissement"));
                                }
                                else {
                                    $user->set_value("org",
$ldap_default_org);
                                }

                                # Attribuer l'adresse de l'utilisateur
                                my $address =
$ldap_entry->get_value("postalAddress")
                                    . "\n"
                                    . $ldap_entry->get_value("postalCode")
                                    . " "
                                    . $ldap_entry->get_value("l");
                                $user->set_value("address", $address);
                                $user->set_value("country",
$ldap_default_country);

                                # Attribuer L'URL
                                $user->set_value("url",
$ldap_entry->get_value("labeledURI"));

                                # Enregistrement des infos utilisateurs
                                $user->commit();

                                $self->{current_user} = $user;
                            }
                        }
                    }
                }
            }
            else {
                $self->{current_user} = $self->_current_user_auth_cookie;
            }
        }
        else {
            $self->{current_user} = $self->_current_user_auth_basic;
        }
    }
    return $self->{current_user};
}


I have used a second method for the CAS Auth, using the mod_auth_cas, but
it also doesn't work :
in *mod_cas.conf* :
<IfModule mod_auth_cas.c>
CASVersion 2
CASDebug On
CASValidateServer Off
CASLoginURL https://[myCasHOST]/login
CASValidateURL https://[myCasHOST]/serviceValidate
CASCookiePath /var/cache/apache2/mod_auth_cas/
</IfModule>

in *apachevhost.conf*
<Directory "/opt/eprints3/cgi/cas">
AuthType CAS
require valid-user
</Directory>

in *archives/<archiveId>/cfg/cfg.d/cas.pl <http://cas.pl>*
$c->{get_login_url} = sub {
    my( $session, $target ) = @_;
    my $uri = $session->get_request->uri;
    if( defined $uri && $uri eq '/cgi/users/login' ){
        return undef;
    }
    my $url = URI->new( $session->get_repository->get_conf( "http_url" ) .
"/cgi/cas/login" );
    $url->query_form( target => $target );
    return "$url";
};

$c->{on_logout} = sub {
    my( $session ) = @_;
    my $username = '';
    $username = $session->current_user->get_value( "username" ) if( defined
$session->current_user );
    # redirect to CAS logout
    $session->redirect( "https://<myCasHOST>/cas/logout" ) unless(
$username eq 'admin' );
}

in *cgi/cas/login*
use EPrints;
use strict;
my $session = new EPrints::Session;
exit( 0 ) unless( defined $session );
my $page=$session->make_doc_fragment();
if( $session->get_repository->can_call( 'on_logout' ) ){
    $session->get_repository->call( 'on_logout', $session );
}

# to allow CAS to work with local admin account:
my $username = '';
$username = $session->current_user->get_value( "username" ) if(defined
$session->current_user );
my $ticketid = EPrints::Apache::AnApache::cookie( $session->get_request,
"eprints_session" );
my $dataset = $session->get_repository->get_dataset( "loginticket" );
$session->get_database->delete_from(
    $dataset->get_sql_table_name(),
    ["code"],
    [$ticketid],
);
$session->logout;

# to allow CAS logout to work
exit unless($username eq 'admin');;
$page->appendChild( $session->render_message(
    "message",
    $session->make_text( "Logout OK!" ) ) );
$page->appendChild( $session->html_phrase( "general:frontpage_link" ) );
my $title = $session->make_text( "Logout" );
$session->build_page( $title, $page, "login" );
$session->send_page();
$session->terminate;
exit;

Hoping to have an answer soon...

Thank you

Matthieu
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mailman.ecs.soton.ac.uk/pipermail/eprints-tech/attachments/20141125/16b4c160/attachment-0001.html