heiglandreas / authLdap

LDAP-Authentication for WordPress
http://andreas.heigl.org/cat/dev/wp/authldap/
MIT License
69 stars 38 forks source link

Create LDAP user for new wordpress user registration #65

Open wtfiwtz opened 9 years ago

wtfiwtz commented 9 years ago

Some plugin users may want this capability... here is a quick 'n' dirty version (doesn't create LDAP groups, doesn't use authLdap config, forced to use 'cn' attribute, not terribly secure, limited to MD5 hashes).

At the moment I hook the woocommerce new customer filter, but it could also be an equivalent wordpress hook for wp_insert_user(such as the pre_user_pass filter and/or user_register action):

function authLdap_woocommerceNewCustomerData($data) {

    $ldap_rdn = 'cn=admin,dc=company,dc=com';
    $ldap_pw = 'adminpw';
    $ldap_orgunit = 'ou=people,dc=company,dc=com';

    $ldap_conn = ldap_connect("ldap://id.company.com", 389);
    if ($ldap_conn) {
        ldap_set_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION, 3);
        $ldap_bind = ldap_bind($ldap_conn, $ldap_rdn, $ldap_pw);
        if ($ldap_bind) {

            // Check to see if the user exists
            $searched = ldap_search($ldap_conn, $ldap_orgunit, 'cn=' . $data['user_login'], array('cn'));
            $entries = ldap_get_entries($ds, $sr);
            if ($entries['count'] > 0) {
                authLdap_debug("User already exists: " . $data['user_login'] . " in LDAP server");
                ldap_close($ldap_conn);
                return null;
            }

            // Add the user
            $ldap_entry = array();
            $ldap_entry['cn'] = $data['user_login'];
            $ldap_entry['givenName'] = $data['user_login'];
            $ldap_entry['sn'] = $data['user_login'];
            $ldap_entry['mail'] = $data['user_email'];  
            $ldap_entry['objectclass'][0] = 'top';
            $ldap_entry['objectclass'][1] = 'person';
            $ldap_entry['objectclass'][2] = 'organizationalPerson';
            $ldap_entry['objectclass'][3] = 'inetOrgPerson';
            $ldap_entry['userPassword'] = '{MD5}' . base64_encode(pack('H*',md5($data['user_pass'])));

            $added = ldap_add($ldap_conn, "cn=" . $data['user_login'] . ',' . $ldap_orgunit, $ldap_entry);
            if (!$added) {
                authLdap_debug("Cannot add user " . $data['user_login'] . " to LDAP server");
                ldap_close($ldap_conn);
                return null;
            }

        } else {
            authLdap_debug("Cannot bind to LDAP server with admin account");
            ldap_close($ldap_conn);
            return null;
        }

    } else {
        authLdap_debug("Cannot connect to LDAP server with admin account");
        ldap_close($ldap_conn);
        return null;
    }

    ldap_close($ldap_conn);
    return $data;
}

...
add_action('woocommerce_new_customer_data', 'authLdap_woocommerceNewCustomerData');
heiglandreas commented 9 years ago

Hi @wtfiwtz.

Thanks for your contribution!

But: I won't add this to the plugin as it's Out-Of-Scope.

The plugins scope is to authenticate users against a central LDAP. Creating users in a central Directory is in most cases not only a matter of adding the user but of underlying formal processes that have to be used to get a user added to the LDAP. It's not a programatical issue but a workflow thing.

I'll leave this open as a reference for users that may want to implement it on their own but it will not find it's way into the current plugin.

Nevertheless Thank you for your time and effort put into providiing this solution!

vercotux commented 8 years ago

Are there any plugin solutions out there for WordPress which do cover this scope? I was unable to find any. Like authLdap, all of them seem to only cover authentication of pre-existing LDAP users.

heiglandreas commented 8 years ago

Hey @vercotux. I'm not aware of one as it's not really the scope of Wordpress. Setting up an LDAP-Server only for use with wordpress is usually much more complex than using the built-in user-management. And if you actually need an LDAP for management of your wordpress users, it's because there already is an LDAP around. And that usually comes with it's own toolchain and authenticating users for wordpress is just an added benefit.

ActiveDirectory (Microsoft) and OpenDirectory (Apple) - and I'm sure a lot of others - comes with their very own UI to manage users (and much more). Free and Open LDAP-Implementations will usually be administered with a web-backend like GOsa or phpLDAPadmin.

But as those cover much much more than a Wordpress-installation there is no plugin for wordpress that does add users to an LDAP-Server.

bilbo-the-hobbit commented 8 years ago

hello,

and don't forget Fusiondirectory who is certified to work with OpenLDAP and has roles working perfectly with wordpress :)

A happy user of authLdap

heiglandreas commented 8 years ago

Oh, Nice one @bilbo-the-hobbit! I didn't know about that one yet :wink:

It's never too late to lear something new!

vercotux commented 8 years ago

What would you guys suggest as the goto solution for a network of (mainly, but not exclusively) WordPress websites which all need to share user accounts for SSO where users register at any one of them and instantly gain access to the rest? I assumed it could be done with LDAP, but apparently not since there is no way to actually add users at any of the sites without first sending them to some kind of 3rd-party offsite location just to signup. Is that what FusionDirectory can be used for? How? I'm sorry, I'm very new to LDAP and this is all extremely confusing.

heiglandreas commented 8 years ago

For me that sounds like a multisite-installation. And there seems to be something that adds a user to each site: https://de.wordpress.org/plugins/multisite-user-management but I'm not sure that's the best solution.

You might want to have a read on https://premium.wpmudev.org/blog/7-plugins-for-easier-wordpress-multisite-user-management/.

Not sure that helps but I think those are better solutions than setting up an LDAP ;)

vercotux commented 8 years ago

WordPress Multisite definitely won't work for this, because it's only good for.. well, WordPress sites. As I said there are other non-WordPress websites and services involved, which all need a standardized way to access a centralized directory of users. Isn't that precisely what LDAP is ideal for?

bilbo-the-hobbit commented 8 years ago

hello,

yes in this case i would suggest OpenLDAP, FusionDirectory, and lemonldap:ng :)

But this is just a bug report :P

vercotux commented 8 years ago

@bilbo-the-hobbit Alright, thank you so much. I will give it a try! I will stop spamming here, as it is getting rather offtopic. Thanks everyone for the insights.

heiglandreas commented 8 years ago

Ah, sorry. I see.

This is a very special use-case, so it might actually be worth having a look at the issue. Did you already figure out how to setup the LDAP-Server? Because that might be the big issue in this case. I might be able to hack something together that would be able to add usaers to a central LDAP using the code provided by @wtfiwtz

heiglandreas commented 8 years ago

As a matter of fact, it's not only an issue but also a documentation part. And as such it's a great discussion for other users as well! So no worries ;)

heiglandreas commented 8 years ago

@vercotux: I took some time to dig deeper into this and have to say, that it's not possible without patching the WP-core.

The issue is as follows: The point I can hook into is when the user-data of a newly created (or an updated) user is stored to the database. That's possible by using the user_register or profile_update-hook that wordpress provides. Sadly the only parameter given there is the users ID in the database. No Password. So I can only retrieve the prehashed password from the database that doesn't make sense at all as I would need it unhashed to hash it differently for usage as password in the LDAP. And as one of the first things that happens in the wp_insert_user-function is prehashing the password, so that there's no way of getting to it without having to patch the WP-core-files (especially the user.php-file) which in turn could introduce a security-hole in your wordpress-installations. And I wouldn't want to be responsible for that.

So what else could there be done?

You can always create an app that asks for user-information and adds them directly to the LDAP and add the link to that URL using the register_url-filter like this:

add_filter('register_url', function($url){
    return 'http://example.com/link/to/my/registration.php';
});

After registration you can then redirect the user back to the WP-instance they were coming from where they can then login using their credentials they just entered.

Sorry, but that seems to be the only really decent solution.