EPrints Technical Mailing List Archive
See the EPrints wiki for instructions on how to join this mailing list and related information.
Message: #03617
< Previous (by date) | Next (by date) > | < Previous (in thread) | Next (in thread) > | Messages - Most Recent First | Threads - Most Recent First
[EP-tech] Eprints CAS Authentification
- To: eprints-tech@ecs.soton.ac.uk
- Subject: [EP-tech] Eprints CAS Authentification
- From: matthieu dolez <matthieu.dolez@gmail.com>
- Date: Tue, 25 Nov 2014 10:32:35 +0100
Hello,
I have some problems in the developpement of a CAS Auth for EPrints.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;
$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};
}
{
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>
<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>
<Directory "/opt/eprints3/cgi/cas">
AuthType CAS
require valid-user
</Directory>
in archives/<archiveId>/cfg/cfg.d/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 = "" $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' );
}
my( $session, $target ) = @_;
my $uri = $session->get_request->uri;
if( defined $uri && $uri eq '/cgi/users/login' ){
return undef;
}
my $url = "" $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;
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
- Prev by Date: [EP-tech] Re: Min Resolution on date fields
- Next by Date: [EP-tech] Different Results from Search/Advanced Search
- Previous by thread: [EP-tech] Min Resolution on date fields
- Next by thread: [EP-tech] Different Results from Search/Advanced Search
- Index(es):