I'm looking for a way to authenticate users through LDAP with PHP (with Active Directory being the provider). Ideally, it should be able to run on IIS 7 (adLDAP does it on Apache). Anyone had done anything similar, with success?
Edit: I'd prefer a library/class with code that's ready to go... It'd be silly to invent the wheel when someone has already done so.
Importing a whole library seems inefficient when all you need is essentially two lines of code...
$ldap = ldap_connect("ldap.example.com");
if ($bind = ldap_bind($ldap, $_POST['username'], $_POST['password'])) {
// log them in!
} else {
// error message
}
You would think that simply authenticating a user in Active Directory would be a pretty simple process using LDAP in PHP without the need for a library. But there are a lot of things that can complicate it pretty fast:
You must validate input. An empty username/password would pass otherwise.
You should ensure the username/password is properly encoded when binding.
You should be encrypting the connection using TLS.
Using separate LDAP servers for redundancy in case one is down.
Getting an informative error message if authentication fails.
It's actually easier in most cases to use a LDAP library supporting the above. I ultimately ended up rolling my own library which handles all the above points: LdapTools (Well, not just for authentication, it can do much more). It can be used like the following:
use LdapTools\Configuration;
use LdapTools\DomainConfiguration;
use LdapTools\LdapManager;
$domain = (new DomainConfiguration('example.com'))
->setUsername('username') # A separate AD service account used by your app
->setPassword('password')
->setServers(['dc1', 'dc2', 'dc3'])
->setUseTls(true);
$config = new Configuration($domain);
$ldap = new LdapManager($config);
if (!$ldap->authenticate($username, $password, $message)) {
echo "Error: $message";
} else {
// Do something...
}
The authenticate call above will:
Validate that neither the username or password is empty.
Ensure the username/password is properly encoded (UTF-8 by default)
Try an alternate LDAP server in case one is down.
Encrypt the authentication request using TLS.
Provide additional information if it failed (ie. locked/disabled account, etc)
There are other libraries to do this too (Such as Adldap2). However, I felt compelled enough to provide some additional information as the most up-voted answer is actually a security risk to rely on with no input validation done and not using TLS.
ldaps://
format for the connection is deprecated. In my example, when you specify setUseTls(true)
it uses ldap://
format and then issues a StartTLS using ldap_start_tls($connection)
. So TLS itself hasn't been deprecated, just connecting using ldaps://
(which actually connects to LDAP over a completely different port).
I do this simply by passing the user credentials to ldap_bind().
http://php.net/manual/en/function.ldap-bind.php
If the account can bind to LDAP, it's valid; if it can't, it's not. If all you're doing is authentication (not account management), I don't see the need for a library.
I like the Zend_Ldap Class, you can use only this class in your project, without the Zend Framework.
PHP has libraries: http://ca.php.net/ldap
PEAR also has a number of packages: http://pear.php.net/search.php?q=ldap&in=packages&x=0&y=0
I haven't used either, but I was going to at one point and they seemed like they should work.
For those looking for a complete example check out http://www.exchangecore.com/blog/how-use-ldap-active-directory-authentication-php/.
I have tested this connecting to both Windows Server 2003 and Windows Server 2008 R2 domain controllers from a Windows Server 2003 Web Server (IIS6) and from a windows server 2012 enterprise running IIS 8.
Success story sharing
ldap_set_option
to make it behave in a different way. Perhaps setting the protocol version? You will have to experiment. I would personally suggest you check for an empty password anyway, just to be safe.ldap_bind
would be handling it and special characters aren't an issue.