EPrints Technical Mailing List Archive

Message: #05236


< Previous (by date) | Next (by date) > | < Previous (in thread) | Next (in thread) > | Messages - Most Recent First | Threads - Most Recent First

[EP-tech] Re: With LDAP user_login.pl script local users can’t login


This is my implementation using LDAP and Kerberos. As you can see I validate Admin separately, but definitively it can be modify to suit Brian workflow.
I hope this helps,

Denis

PS: do not hesitate in suggesting improvements! :D

$c->{check_user_password} = sub {
   my( $session, $username, $password ) = @_;
  
   # Kerberos authentication for "user", "editor" and "admin" types (roles)
  
   use Net::LDAP; # IO::Socket::SSL also required
   use Authen::Krb5::Simple;
   use Authen::SASL;
  
   # LDAP tunables
   my $ldap_host = “ldap.xxx.xxx";
   my $base      = “OU=xx,DC=xx,DC=xx,DC=xx,DC=xx";
   my $proxy_user ="ad_read";
   my $dn        = "CN=$proxy_user,$base";

   # Kerberos tunables
   my $krb_host = “xxx.xxx.xxx";
  
   my $krb       = Authen::Krb5::Simple->new(realm => $krb_host);
   unless ( $krb )
   {
    print STDERR "Kerberos error: $@\n";
    return 0;
   }

   my $ldap      = Net::LDAP->new ( $ldap_host );
   unless( $ldap )
   {
       print STDERR "LDAP error: $@\n";
       return 0;
   }
  
   my $sasl = Authen::SASL->new(
          mechanism => 'GSSAPI',
          callback => { user => 'ad_read' }
        ) or die "$@";

   my $mesg = $ldap->bind(sasl => $sasl);# dn => $dn, password=>$ldappass );

   if( $mesg->code() )
   {
       print STDERR "LDAP Bind error: " . $mesg->error() . "\n";
       return 0;
   }

   # Distinguished name (and attribues needed later on) for this user
   my $result = $ldap->search (
       base    => "$base",
       filter  => "(&(sAMAccountName=$username))",
       attrs   =>  ['1.1', 'uid', 'sn', 'givenname', 'mail'],
       sizelimit=>1
   );

   my $entr = $result->pop_entry;
   unless( defined $entr )
   {
       # Allow local EPrints authentication for admins (accounts not found in LDAP)
       my $user = EPrints::DataObj::User::user_with_username( $session, $username );
       return 0 unless $user;

       my $user_type = $user->get_type;
       if( $user_type eq "admin" )
       {
           # internal authentication for "admin" type
           return $session->get_database->valid_login( $username, $password );
       }
       return 0;
   }

  
   # Check password
   if( !$krb->authenticate( $username, $password ) )
   {
    print STDERR "$username authentication failed: ", $krb->errstr(), "\n";
       return 0;
   }
  
   # Does account already exist?
   my $user = EPrints::DataObj::User::user_with_username( $session, $username );
   if( !defined $user )
   {
       # New account
       $user = EPrints::DataObj::User::create( $session, "user" );
       $user->set_value( "username", $username );
   }
  
   # Set metadata
   my $name = {};
   $name->{family} = $entr->get_value( "sn" );
   $name->{given} = $entr->get_value( "givenName" );
   $user->set_value( "name", $name );
   $user->set_value( "username", $username );
   $user->set_value( "email", $entr->get_value( "mail" ) );
   $user->commit();
  
   $ldap->unbind if $ldap;
  
   return 1;
}


On Thu, Dec 3, 2015 at 4:52 PM, Brian D. Gregg <bdgregg@pitt.edu> wrote:

Our logic flow for LDAP and local logins is as follows and we had to pretty much write (re-write) our eprints_login.pl from scratch, but we had to do that for other reasons here as well due to the LDAP connection we needed to use to our central authentication system.  Our flow assumes that everyone logging in has a LDAP account first then tries the local DB if LDAP logon fails.

 

Hope this helps.

-Brian.