Log in

Stats

  • Category: Authentication
  • License: GNU General Public License (GPL) version 2
  • Updated: 2010-4-16
  • Downloads: 4115
  • Recommendations: 6

Releases


Previous releases:

LDAP authentication plugin for Elgg 1.8

Last updated 782 days ago

LDAP authentication plugin (Edit your project's description!)

Release Notes:

Adapted for Elgg 1.8

Comments

  • Chris Myers 765 days ago

    Strugging to get it working, as no feedback appears to be provided for the failure.

    Checked apache logs & /var/log folder for any sort of log.

    Hoping for a bit of info.... :-)

     

  • Bruno Grossmann 765 days ago

    If you turn on Elgg debug (in administration), you should get some messages in error_log. A few pointers

    1) Make sure your PHP is compiled with the LDAP module (line if (!function_exists('ldap_connect')) return false; in start.php)

    2) Make sure you do not have TLS turned on (needs a lot more configuration, CA certificates, etc)

    3) Use network sniffer (wireshark, tcpdump) to check a connection is being initiated to the LDAP host

  • Chris Myers 765 days ago

    Thanks Bruno... I got somewhere.

    Just a note for others - After enabling Elgg debug, use the linux commandline to see the apache log:

    tail -f -n 50 /var/log/apache2/error.log

    I originally had authentication problems, these are now fixed

    The error I am getting now is:

    -----

    Deprecated in 1.8: find_plugin_setting() is deprecated by elgg_get_calling_plugin_entity() or elgg_get_plugin_from_id() Called from [#6] /var/www/XXX/mod/ldap_auth/start.php:44, referer: http://XXX/

    PHP WARNING: 2012-03-20 10:25:33 (UTC): "ldap_search(): Search: Operations error" in file /var/www/XXX/mod/ldap_auth/start.php (line 259), referer: http://XXX/

    ERROR: Unable to perform LDAP search: Operations error, referer: http://XXX/

    ----

    I have hit a wall now, as I have no idea how to fix this.

     

    Many thanks.

  • Bruno Grossmann 765 days ago

    I will fix the deprecated message but it is only a warning.

    As far as the other error, this tells me you probably connected properly to the LDAP server, but the Distinguished Name (DN) you authenticated with could not perform the search. I also note that you seem to be getting an LDAP  referral back. Possible issues: wrong search base DN or user is not allowed to perform the search.

    Do you have access to an LDAP client? I use jXplorer. The first thing I would try is to point jXplorer at the LDAP directory, bind as the user configured in the plugin and try to perform the search on the base DN configured in the plugin. If this works, then it means the problem is with the plugin. Otherwise, it's a permission or configuration problem.

  • Chris Myers 764 days ago

    OK then.. Used Jxplorer & authenticated with the credentials & base DN.

    Did a search for a sAMAccountName user & it returned details successfully.

    P.S. These are the details I am using to authenticate phpBB on the same virtualhost.

  • Bruno Grossmann 764 days ago

    So you use SAMAcountName in the username filter attribute. What do you use for the search attributes? You obvisouly got the connectivity part right since you are getting an operation error message from your AD. At this point, I can only speculate at what it could be: mispelled attribute, ACL. Basically, the plugin will perform an authenticated bind with the DN and password, then perform an LDAP search like "SAMAcountName" = "bruno" and ask for the list of attributes in the search attribute box. If a match is found, it tries to bind with username "bruno" and the password typed in the Elgg password textbox. I suspect the operation error comes from the search operation (not the bind) but I could be wrong. Any logs on the AD side to help you? Is wireshark or tcpdump a possibility?

  • Chris Myers 764 days ago

    Found it.. Its working! I will share my findings:

    My search path base dn was the entire domain. It was obviously too much for the poor thing!

     

    My users are in two places so I used the following base DN search:

    OU=Pupils,DC=w,DC=x,DC=y,DC=z : OU=Staff,DC=w,DC=x,DC=y,DC=z

    (Obviously I have obscured my domain in the example)

     

    Many Thanks Bruno for your help.

  • stanislas93 744 days ago

    Hi

    Thanks a lot for your plugin.

    We modified the plugin to integrate an LDAP filter.

    Would you be interested in integrating it into the future version of ldap_auth?

    Regards

    Stan

  • Alastair 737 days ago

    Is there any facility for NTLM and/or Kerberos transparent authentication with this plugin?

  • Bruno Grossmann 737 days ago

    No. As you probably know, NTLM/Kerberos authentication is usually handled by the Web server with a combination of NTLM or Kerberos support (e.g. winbind). Once you have access to the PHP_AUTH_USER variable, you can make use of it in any module, including this one.

    I found the URL below to be useful.

    http://adldap.sourceforge.net/wiki/doku.php?id=mod_auth_ntlm_winbind

  • Alastair 737 days ago

    Thanks for the quick reply - we're just evaluating ELGG for use on out Windows network so if we do I'll probably need to add support for transparent login so I'll be sure to share. For now however, unfortunately I can't even get the forms based login to work with our Active Directory. Do you know how the plugin behaves in a forest - can we point the plugin at the Global Catalog?

  • Bruno Grossmann 737 days ago

    The plugin engine is a standard LDAP client. In other word, if you can do something with an LDAP client (e.g., jXplorer), you should be able to do the same thing with the plugin. If the forest is composed of multiple base DNs, you can actually configure the plugin to read them one after the other (colon-separated). As you can see from the previous post, make sure you are not retrieving too many entries - you may hit a server limit.

  • Alastair 737 days ago

    Doh! Forgot to restart apache after installing php5_ldap. Facepalm...

  • Alastair 736 days ago

    Cool so I now have LDAP working lovely with the standard forms auth, and have mod_auth_kerb all playing nicely with $_SERVER["REMOTE_USER"] populated with my active directory UPN. I was wondering if you have any thoughts on where to start with hacking in support for this within Elgg - it seems I could add a config option into your plugin to pickup REMOTE_USER instead of binding the user's password. But also it seems I'd have to make a change to the core of Elgg to get it to attempt a transparent auth instead of displaying the login form. Does that sound accurate? Would be very grateful to have your thoughts on this. I have a reasonable amount of PHP experience so if I implement this I will definitely share what I have. Cheers

  • Alastair 736 days ago

    Just spotted elgg_trigger_plugin_hook, looks promising

  • Bruno Grossmann 736 days ago

    Using PAM makes it pretty easy. Below is my start.php The rest of the code is exactly the same as in the LDAP module. I have just rename my module to ntlm_sso and my functions ntlm_ instead of ldap_

    function ntlm_auth_init()
    {
        global $CONFIG;
        $credentials['username'] = 'dummy';
        $credentials['password'] = 'user';
        // Override save method
        elgg_register_action('ntlm_sso/settings/save',$CONFIG->pluginspath . 'ntlm_sso/actions/plugins/settings/save.php');
        // Register the authentication handler
        register_pam_handler('ntlm_auth_authenticate');
        register_translations($CONFIG->pluginspath . "ntlm_sso/languages/");
        if (!elgg_is_logged_in() && $_SERVER['PHP_AUTH_USER'])
        {
            $username = $_SERVER['PHP_AUTH_USER'];
                $result=elgg_authenticate($username,'dummy');
            if ($result !== true) {
                register_error($result);
            }
            else
            {
                forward(REFERER);
            }
        }
    }
    /**
    * NTLM authentication
    *
    * @param mixed $credentials PAM handler specific credentials
    * @return boolean
    */
    function ntlm_auth_authenticate($credentials = null)
    {
        // Nothing to do if LDAP module not installed
        $user_create = elgg_get_plugin_setting('user_create', 'ntlm_sso');
        // Get configuration settings
        $config = find_plugin_settings('ntlm_sso');
               
        // Nothing to do if not configured
        if (!$config)
        {
            return false;
        }
        $username      = null;
        // Check SERVER variables to check if user was authenticated (nothing to do otherwise)
        //if ($_SERVER['PHP_AUTH_USER'] && ($_SERVER['AUTH_TYPE'] == 'NTLM'))
        if ($_SERVER['PHP_AUTH_USER'])
        {
            $username = $_SERVER['PHP_AUTH_USER'];
        } else {
            return false;
        }
       
        // Perform the authentication
        return ldap_auth_check($config, $username,$user_create);
    }
       
    /**
    * Perform an LDAP authentication check
    *
    * @param ElggPlugin $config
    * @param string $username
    * @param string $password
    * @return boolean
    */
    function ldap_auth_check($config, $username,$user_create)
    {
        if ($user = get_user_by_username($username))
        {
            return login($user);
        }
        else
        {
       
            if ($user_create == 'on')
            {
                if (!function_exists('ldap_connect'))
                {
                     elgg_log("BRUNO ntlm_sso no ldap_connect", 'NOTICE');
                     return false;
                }
                $host        = elgg_get_plugin_setting('hostname', 'ntlm_sso');
       
                // No point continuing
                if(empty($host))
                {
                    elgg_log("LDAP error: no host configured.",'ERROR');
                return;
                }
       
                $port        = elgg_get_plugin_setting('port', 'ntlm_sso');
                $version     = elgg_get_plugin_setting('version', 'ntlm_sso');
                $basedn      = elgg_get_plugin_setting('basedn', 'ntlm_sso');
                $filter_attr = elgg_get_plugin_setting('filter_attr', 'ntlm_sso');
                $search_attr = elgg_get_plugin_setting('search_attr', 'ntlm_sso');
                $bind_dn     = elgg_get_plugin_setting('ldap_bind_dn', 'ntlm_sso');
                $bind_pwd    = elgg_get_plugin_setting('ldap_bind_pwd', 'ntlm_sso');
                $user_create = elgg_get_plugin_setting('user_create', 'ntlm_sso');
                $start_tls   = elgg_get_plugin_setting('start_tls', 'ntlm_sso');
           
                ($user_create == 'on') ? $user_create = true : $user_create = false;
                ($start_tls == 'on') ? $start_tls = true : $start_tls = false;
                $port        ? $port        : $port = 389;
                $version     ? $version     : $version = 3;
                $filter_attr ? $filter_attr : $filter_attr = 'uid';
                $basedn      ? $basedn = array_map('trim', explode(':', $basedn)) : $basedn = array();
       
                if (!empty($search_attr))
                {
                    // $search_attr as in "email:email_address, name:name_name";
                    $pairs = array_map('trim',explode(',', $search_attr));
                    $values = array();
                    foreach ($pairs as $pair)
                    {
                        $parts = array_map('trim', explode(':', $pair));
                        $values[$parts[0]] = $parts[1];
                    }
                    $search_attr = $values;
                } else {
                    $search_attr = array('dn' => 'dn');
                }
       
                // Create a connection
                if ($ds = ldap_auth_connect($host, $port, $version, $bind_dn, $bind_pwd))
                {
                    if ($start_tls and !ldap_start_tls($ds)) return false;
                    // Perform a search
                    foreach ($basedn as $this_ldap_basedn)
                    {
                        $ldap_user_info = ldap_auth_do_auth($ds, $this_ldap_basedn, $username, $filter_attr, $search_attr);

                        if($ldap_user_info)
                        {
                                        // Valid login but user doesn't exist
                            $name  = $ldap_user_info['lastname'];
                                            if (isset($ldap_user_info['firstname']))
                            {
                                $name  = $ldap_user_info['lastname']." ".$name;
                            }
                                            ($ldap_user_info['mail']) ? $email = $ldap_user_info['mail'] : $email = null;
                            //Need to do something with password field since password cannot be empty
                            $password=rand();
                            if ($user_guid = register_user($username, $password, $name, $email))
                            {
                                // Success, credentials valid and account has been created                               
                                return true;
                            } else {
                                register_error(elgg_echo('ntlm_sso:no_register'));
                                                return false;
                                            }
                        }
                    }
                    // Close the connection
                    ldap_close($ds);
                    register_error(elgg_echo("ntlm_sso:no_account"));
                    return false;
                    }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
    }
       
    /**
    * Create an LDAP connection
    *
    * @param string $host
    * @param int $port
    * @param int $version
    * @param string $bind_dn
    * @param string $bind_pwd
    * @return mixed LDAP link identifier on success, or false on error
    */
    function ldap_auth_connect($host, $port, $version, $bind_dn, $bind_pwd)
    {
        $ds = ldap_connect($host, $port);
        ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, $version);
        // Start the LDAP bind process
        $ldapbind = null;
        if ($ds)
        {
            if ($bind_dn != '')
            {
                $ldapbind = ldap_bind($ds, $bind_dn, $bind_pwd);
            }
            else
            {
                // Anonymous bind
                $ldapbind = ldap_bind($ds);
            }
        }
        else
        {
            // Unable to connect
            elgg_log('Unable to connect to the LDAP server: '.ldap_error($ds),'ERROR');
            return false;
        }
        if (!$ldapbind)
        {
            elgg_log('Unable to bind to the LDAP server with provided credentials: '.ldap_error($ds),'ERROR');
            ldap_close($ds);
            return false;
        }
        return $ds;
    }
       
    /**
    * Performs LDAP search to find user entry
    *
    * @param object $ds LDAP link identifier
    * @param string $basedn
    * @param string $username
    * @param string $password
    * @param string $filter_attr
    * @param string $search_attr
    * @return mixed array with search attributes or false on error
    */
    function ldap_auth_do_auth($ds, $basedn, $username, $filter_attr, $search_attr)
    {
        $sr = ldap_search($ds, $basedn, $filter_attr ."=". $username, array_values($search_attr));
        if(!$sr)
        {
            elgg_log('Unable to perform LDAP search: '.ldap_error($ds),'ERROR');
            return false;
        }
        $entry = ldap_get_entries($ds, $sr);
        if(!$entry or !$entry[0])
        {
            return false; // didn't find username
        }
        foreach (array_keys($search_attr) as $attr)
        {
            $ldap_user_info[$attr] = $entry[0][$search_attr[$attr]][0];
        }
        return $ldap_user_info;
    }
    elgg_register_event_handler('init','system','ntlm_auth_init');
    ?>

  • Alastair 736 days ago

    That looks spot on, is there any chance you could send me your ntlm_sso mod folder as a zip?

    Thanks so much for you help!

    Cheers

  • Alastair 736 days ago

    No worries if you don't have time, I've renamed enough stuff to get it working. One thing I've spotted is that it uses last name twice for new accounts:

     

                            $name  = $ldap_user_info['lastname'];

                            if (isset($ldap_user_info['firstname']))

                            {

                                $name  = $ldap_user_info['lastname']." ".$name;

                            }

     

  • Bruno Grossmann 736 days ago

    1) Need your email address to email the zip file

    2) Bug. Thanks :-)

  • Artur Oliveira 699 days ago

    Do you have the ntlm_sso available ?
    Could you please share the mod ?
    Thanks in advance

  • Artur Oliveira 649 days ago

    I made some changes to the code of version 0.2 to include:

    • Debugging info to log some errors to make the process of troubleshooting
    • Added support for apache based authentication for modules that set the vaiable $_SERVER['REMOTE_USER'] to support single-sign-on
      • I implemented single-sign-on against Windows Domain/Active Directory using Apache2::AuthenNTLM perl module.

    If anyone is interested i can send you the size file

  • alagu.sathappan 443 days ago

    Hi Burno,

    i tried configuring this plugin with our elgg setup yet there is no response when AD user login who not exists in Elgg DB. It's much apperciated if youcould you kindly advise us on this issue. i have also posted  my config below

    :Apps.dp.ad

    LDAP port: 389

    LDAP version:3

    LDAP bind cn: DN path of admin account

    Bind password: password of  above admin acc

    Based DN: OU=DP Users,DC=APPS,DC=DP,DC=AD

    filter attribute : SAMNameAccount

    : firstname:givenname, lastname:sn, mail:mail

    Create use: enabled

    start TLS: Disabled

  • Bruno Grossmann 443 days ago

    Hello,

    I do not think I can test from where I am. My first question would be: are you sure you are connecting and binding properly? You can either use Wireshark or check your AD logs to make ure you are indeed connecting and authenticating.

    I also remember someone having a problem with performing a search from too high in the DIT. Make sure your search base allows you to perform a subtree search.

    And note that the filter attribute for AD should be SAMAccountName, not SAMNameAccount

  • DavidJ411 147 days ago

    Does this plugin work?

     

    it does not seem to register or even run the init (i put some print statements in there to be sure).