I was asked by my present employer to provide a standard method for authentication for many of our intranet Web services. One of the major issues we faced was that our company uses two major platforms: UNIX and Windows. So, my first suggestion didn't go over too well: Move every one to UNIX or Linux and get rid of Windows.
I decided the best way to solve the problem with the current UNIX/Windows setup was by utilizing the LDAP features of PHP. For the LDAP server, I was required to use the existing system, which is primarily a huge Microsoft Exchange Server system. I wasn't too excited to work with Exchange, but it has proven reliable and the LDAP features are extremely easy to use and configure. However, please note that this is not the most secure method of authentication. If the highest level of security is required, then the use of LDAP and SSL is highly encouraged.
Where to begin
To get started, I'll provide a list of the main PHP LDAP functions with a very brief explanation of their purpose. Then, I'll demonstrate how to connect to an LDAP server and use it for authenticating a user. By providing code samples, I will demonstrate PHP’s ability to connect and bind to an LDAP server.
A perfect match: PHP and LDAP
Here is the list of the functions that I will use in my examples. These are also available online.
- · ldap_connect—Used to connect to the LDAP server
- · ldap_bind—The ability to bind to a specific LDAP directory
- · ldap_error—A way to get error messages from the LDAP server
- · ldap_search—Used to conduct searches
- · ldap_get_entries—Retrieve multiple entries from a search result
- · ldap_close—Close an LDAP connection
Now I'll demonstrate the first function with an example (Listing A) and then discuss the relevance of the function and its purpose.
In Listing A, a connection (resource) to the LDAP server is returned. The ldap_connect function accepts two parameters: host and port. The first parameter, host, is the LDAP host name, and the second parameter is the port where LDAP is running. By default, LDAP runs on port 389. If you require (or desire) a secure connection to the LDAP server, you can change the host to a qualified URL of the LDAP server like this:
$ldap[‘conn’] = ldap_connect( “ldaps://ldap.example.com” );
Here you don't use the port parameter, because you're specifying a URL instead of a server name. One important item to remember is that the server name must be the exact name that corresponds to the SSL certificate.
You now have a connection to the LDAP server, so I'll move on to the binding step and demonstrate how to bind to the server. I use a supplied username and password to do the authentication. By binding to the server, you verify that the username and password pair is correct and that the user is authenticated if binding is successful. If the binding is not successful, the user is not authenticated.
Listing B demonstrates how to bind to the server with a username and password. I created the proper domain name (DN) and used the user’s password to correctly connect to LDAP. By using the DN and password, this allows LDAP to authenticate and bind the connection, resulting in a successful bind. The return type of the ldap_bind function is Boolean. This will allow me to determine if the user supplied the proper credentials to allow for a successful login. Once this process is complete, you know that the user is authenticated.
So what happens if there is an error? The proper way to figure out what errors might have happened is by calling the ldap_error function. The ldap_error function provides a string that contains the last error that occurred on the LDAP server.
In Listing C, I added the ldap_error function to the script to display an error and exit if it could not authenticate the user by binding to the LDAP server. This function returns a string that contains the error message generated by the last command that was sent to the LDAP server. If you could not bind with the given username and password, the error includes something along the lines of an invalid username or password.
For the last example in Listing D, I use the last three functions together: ldap_search, ldap_get_entries, and ldap_close.
After calling the ldap_bind function in Listing D, I request information from the server, searching the server via the ldap_search function. The ldap_search function accepts multiple parameters; however, in this example I used only the first three. I passed the ldap connection, search base, and the filter to the search function that searches the server for the correct user based on the supplied search base and filter. In short, I told it to search for the user by specifying the uid as the username. This causes LDAP to filter the result and return only the user’s LDAP information.
When I first started working with the LDAP extension in PHP, I was confused by the way the ldap_search function returned a resource instead of an array or string. Having overcome my ignorance of that fact, I learned to use the ldap_get_entries function to retrieve the actual results from the search. One good thing to remember about ldap_get_entries is that it returns the results as a multidimensional array. With that said, I stored results in the array called $ldap[‘info’], which might seem somewhat confusing.
Once I have the results from the search in a multidimensional array, I can access the data that I want. I set the user’s department and e-mail address in session variables that I can use later in the current session.
After everything is completed, I close the connection with the ldap_close function. The close function allows me to free up the connection resource. This function is actually an alias to ldap_unbind, which does the same thing.
A good start
Though I haven't touched upon many of the other functions available in the LDAP extension, this is sufficient to get you started with LDAP authentication. PHP and LDAP provide a powerful combination providing a universal method of authenticating users in Web-based applications. The LDAP server allows administrators to issue permissions that, in turn, can be verified and used to allow or deny access to data in the applications.