We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 18726
    • 4 Posts
    Greets to the MODx community.

    Some time ago I wrote this plugin for MODx 1.0 to handle LDAP Authentication. Unfortunately though I was having trouble getting 2.0.0-beta-4 to work in my test environment.

    Recently I updated my test environment and decided to give 2.0.0-beta-5 a spin and lo-and-behold it worked this time. So once I got the CMS up and running, I set to work adapting the LDAP Authentication plugin for 1.0 to function in 2.0. Here are the results:

    <?php
    /*
    LDAP Authentication Plugin
    MODx 2.0.0-beta-5
    January 2010 - Matt Pierce (http://mpierce.pie2k.com)
    This code is provided as-is and without warranty.  It is free to use, copy, modify, and redistribute.
    
    NOTE:
    MODx only allows 2 possible return values for the OnManagerAuthentication event:
    	true	the username/password combination is valid
    	false	the username/password combination IS NOT valid
    
    The problem with this setup is that there's no room for reporting some other type of authentication problem.
    For example, the LDAP server could be temporarily unavailable, or the script may be misconfigured.
    
    It seems that this hasn't escaped the authors.  Since a false return value COULD indicate some other failure
    MODx checks the input values against the local users table.
    
    tl;dr: If your LDAP server fails some day, you should still be able to login with whatever password you set
    in the MODx manager interface.
    */
    
    global $_lang;
    $event_name = $modx->event->name;
    
    if(!class_exists('LDAPAuthorization')) {
    	class LDAPAuthorization {
    	
    		/*
    		You need to provide some information about your LDAP server.  This isn't
    		completely 100% fire-and-forget.  If you don't know these variables then 
    		you need to contact your LDAP administrator to find them out.
    
    		Possible future improvement: Put these values into the plugin properties?
    		Is that easier for site administrators or would they rather edit this code?
    		*/
    		
    		// your ldap server
    		var $LDAP_Server = "ldap.yourdomain.com";
    		var $LDAP_Port = 636; // ldaps=636; ldap=389
    		// the tree on which you should be searching for users
    		var $LDAP_BaseDN = "o=yourdomain.com,dc=yourdomain,dc=com";
    		// the field to match the username with (usually "uid")
    		var $LDAP_SearchField = "uid";
    		// If your LDAP server requires you to use a DN/Password combination to initiate a search, set these variables.
    		// If not, set them to null;
    		var $LDAP_BindDN = "uid=search-accoiunt,ou=generic-accounts,o=yourdomain.com,ou=yourdomain,ou=com";
    		var $LDAP_BindPW = "******";
    
    		
    		
    		// LDAPAuth() : use LDAP to verify a username and password
    		// 	parameters:
    		//		$username	the user's unique id
    		//		$password	the password the user entered on the login form
    		//	returns:
    		//		true		the username/password combination is valid
    		//		false		the username/password combination is not valid OR
    		//				the script was unable to search the directory
    		function LDAPAuth($username, $Password)
    		{
    			// HOW THIS SCRIPT WORKS:
    			// The general idea is to take the username and password given by the user, attempt to use it
    			// to log in to the LDAP directory, then tell the MODx system whether or not the LDAP directory
    			// accepted the credentials.  
    
    			// The catch is that an LDAP directory requires you to provide a DN (distinct name) and password,
    			// not merely a username and password.  So, in order to mesh up the username with the DN, we first
    			// login with some generic account, search for a user with the same username, get the DN, then
    			// try to login with the DN from the search and the password from the login form.
    
    			// connect to the LDAP Server
    			if ($connect_id = @ldap_connect($this->LDAP_Server, $this->LDAP_Port)) {
    				
    				// After connect, bind with some account that will allow us to search for a user's DN.
    				if ($this->LDAP_BindDN && $this->LDAP_BindPW) {
    					// If the preferences are set, bind with the user's serach DN/PW.
    					$search_bind_result = @ldap_bind($connect_id, $this->LDAP_BindDN, $this->LDAP_BindPW);
    				} else {
    					// If not, try an annonymous bind.
    					$search_bind_result = @ldap_bind($connect_id);
    				}
    				// if the bind performed above was successful ...
    				if ($search_bind_result) {
    					
    					// use the username porvided to search for a user with the same username in the directory
    					$attrs = array("dn", "mail", "uid"); // these are the LDAP fields we want to retrieve.
    					$search_id = @ldap_search($connect_id, $this->LDAP_BaseDN, "(".$this->LDAP_SearchField."=".$username.")", $attrs);
    					
    					// get the results of that search
    					$result_array = ldap_get_entries($connect_id, $search_id);
    					if (is_array($result_array) && isset($result_array[0])) {
    						
    						// attempt to bind to the LDAP server with the user's dn and the provided password
    						if (@ldap_bind($connect_id, $result_array[0]['dn'], $Password)) {
    							
    							// if successful, return true, all other cases return false
    							@ldap_close($connect_id);
    							return true;
    						} else {
    							@ldap_close($connect_id);
    							return false;
    						}
    					} else {
    						@ldap_close($connect_id);
    						return false;
    					}
    				} else {
    					@ldap_close($connect_id);
    					return false;
    				}
    			} else {
    				// connection failed, no need to close the connection
    				return false;
    			}
    		}
    	}
    }
    
    // If this is invoked by the "OnManagerAuthentication" event ...
    if($event_name == 'OnManagerAuthentication') {
    	// Create an instance of the authorization object defined above
    	$auth = new LDAPAuthorization;
    
    	// Check the username & password
    	$result = $auth->LDAPAuth($modx->event->params["user"]->username, $modx->event->params["password"]);
    
    	// return the result to MODx
    	$modx->event->_output = $result;
    
    }
    ?>


    (This code is written for 2.0.0-beta-5 and will hopefully work in later versions of 2.0. If you’re looking for one that works in 1.0 see the link above the code.)

    Hopefully this will prove useful to somebody. I know that demand for this sort of thing was relatively high when I wrote the first one - I’m guessing it might still be high now.
      • 3749
      • 24,544 Posts
      Thanks! There have been many requests for LDAP capability for MODx. I’m sure this will help a lot of people and we really appreciate the contribution. laugh

      BTW, you mentioned permission issues in another thread and I thought I’d point you to this: http://bobsguides.com/revolution-permissions.html.

      Although Revolution is still in beta, it is quite solid (running this site and a number of others) and RC1 is due out before too long (we hope).
        Did I help you? Buy me a beer
        Get my Book: MODX:The Official Guide
        MODX info for everyone: http://bobsguides.com/modx.html
        My MODX Extras
        Bob's Guides is now hosted at A2 MODX Hosting
        • 16834
        • 93 Posts
        excellent - many thanks, I look forward to playing with this....

        L
          • 10963
          • 26 Posts
          I’m new to modx. How does one add the code as a plugin or add the code to get this functionality?