| Authen-Simple-LDAP documentation | Contained in the Authen-Simple-LDAP distribution. |
Authen::Simple::LDAP - Simple LDAP authentication
use Authen::Simple::LDAP;
my $ldap = Authen::Simple::LDAP->new(
host => 'ldap.company.com',
basedn => 'ou=People,dc=company,dc=net'
);
if ( $ldap->authenticate( $username, $password ) ) {
# successfull authentication
}
# or as a mod_perl Authen handler
PerlModule Authen::Simple::Apache
PerlModule Authen::Simple::LDAP
PerlSetVar AuthenSimpleLDAP_host "ldap.company.com"
PerlSetVar AuthenSimpleLDAP_basedn "ou=People,dc=company,dc=net"
<Location /protected>
PerlAuthenHandler Authen::Simple::LDAP
AuthType Basic
AuthName "Protected Area"
Require valid-user
</Location>
Authenticate against a LDAP service.
This method takes a hash of parameters. The following options are valid:
Connection host, can be a hostname, IP number or a URI. Defaults to localhost.
host => ldap.company.com
host => 10.0.0.1
host => ldap://ldap.company.com:389
host => ldaps://ldap.company.com
Connection port, default to 389. May be overriden by host if host is a URI.
port => 389
Connection timeout, defaults to 60.
timeout => 60
The LDAP version to use, defaults to 3.
version => 3
The distinguished name to bind to the server with, defaults to bind anonymously.
binddn => 'uid=proxy,cn=users,dc=company,dc=com'
The credentials to bind with.
bindpw => 'secret'
The distinguished name of the search base.
basedn => 'cn=users,dc=company,dc=com'
LDAP filter to use in search, defaults to (uid=%s).
filter => '(uid=%s)'
The search scope, can be base, one or sub, defaults to sub.
filter => 'sub'
Any object that supports debug, info, error and warn.
log => Log::Log4perl->get_logger('Authen::Simple::LDAP')
Returns true on success and false on failure.
my $ldap = Authen::Simple::LDAP->new(
host => 'od.company.com',
basedn => 'cn=users,dc=company,dc=com',
filter => '(&(objectClass=inetOrgPerson)(objectClass=posixAccount)(uid=%s))'
);
my $ldap = Authen::Simple::LDAP->new(
host => 'ad.company.com',
binddn => 'proxyuser@company.com',
bindpw => 'secret',
basedn => 'cn=users,dc=company,dc=com',
filter => '(&(objectClass=organizationalPerson)(objectClass=user)(sAMAccountName=%s))'
);
Active Directory by default does not allow anonymous binds. It's recommended that a proxy user is used that has sufficient rights to search the desired tree and attributes.
Christian Hansen ch@ngmedia.com
This program is free software, you can redistribute it and/or modify it under the same terms as Perl itself.
| Authen-Simple-LDAP documentation | Contained in the Authen-Simple-LDAP distribution. |
package Authen::Simple::LDAP; use strict; use warnings; use base 'Authen::Simple::Adapter'; use Net::LDAP qw[]; use Net::LDAP::Constant qw[LDAP_INVALID_CREDENTIALS]; use Params::Validate qw[]; our $VERSION = 0.2; __PACKAGE__->options({ host => { type => Params::Validate::SCALAR | Params::Validate::ARRAYREF, default => 'localhost', optional => 1 }, port => { type => Params::Validate::SCALAR, default => 389, optional => 1 }, timeout => { type => Params::Validate::SCALAR, default => 60, optional => 1 }, version => { type => Params::Validate::SCALAR, default => 3, optional => 1 }, binddn => { type => Params::Validate::SCALAR, depends => [ 'bindpw' ], optional => 1 }, bindpw => { type => Params::Validate::SCALAR, depends => [ 'binddn' ], optional => 1 }, basedn => { type => Params::Validate::SCALAR, optional => 1 }, scope => { type => Params::Validate::SCALAR, default => 'sub', optional => 1 }, filter => { type => Params::Validate::SCALAR, default => '(uid=%s)', optional => 1 } }); sub check { my ( $self, $username, $password ) = @_; my $connection = Net::LDAP->new( $self->host, Port => $self->port, Timeout => $self->timeout, Version => $self->version ); unless ( defined $connection ) { my $host = $self->host; $self->log->error( qq/Failed to connect to '$host'. Reason: '$@'/ ) if $self->log; return 0; } my ( @credentials, $message, $search, $entry, $filter, $dn ); @credentials = $self->binddn ? ( $self->binddn, password => $self->bindpw ) : (); $message = $connection->bind(@credentials); if ( $message->is_error ) { my $error = $message->error; my $binddn = $self->binddn; my $bind = $binddn ? qq/with dn '$binddn'/ : "Anonymously"; $self->log->error( qq/Failed to bind $bind. Reason: '$error'/ ) if $self->log; return 0; } $filter = sprintf( $self->filter, ($username) x 10 ); $search = $connection->search( base => $self->basedn, scope => $self->scope, filter => $filter, attrs => ['1.1'] ); if ( $search->is_error ) { my $error = $search->error; my $basedn = $self->basedn; my $options = qq/basedn '$basedn' with filter '$filter'/; $self->log->error( qq/Failed to search $options. Reason: '$error'/ ) if $self->log; return 0; } if ( $search->count == 0 ) { $self->log->debug( qq/User '$username' was not found with filter '$filter'./ ) if $self->log; return 0; } if ( $search->count > 1 ) { my $count = $search->count; $self->log->warn( qq/Found $count matching entries for '$username' with filter '$filter'./ ) if $self->log; } $entry = $search->entry(0); $message = $connection->bind( $entry->dn, password => $password ); $dn = $entry->dn; if ( $message->is_error ) { my $error = $message->error; my $level = $message->code == LDAP_INVALID_CREDENTIALS ? 'debug' : 'error'; $self->log->$level( qq/Failed to authenticate user '$username' with dn '$dn'. Reason: '$error'/ ) if $self->log; return 0; } $self->log->debug( qq/Successfully authenticated user '$username' with dn '$dn'./ ) if $self->log; return $dn; } 1; __END__