BlogMatrix
 

OpenID and LDAP

edit David P. Janes 2008-05-14 20:43 UTC 1  comment  ·  ·

Many enterprises - include most I would guess that are Microsoft-centric - use LDAP to establish user identity and profiles.In the Web 2.0 world, the emerging standard is OpenID. Is there a way to use OpenID to provide logins within the Enterprise buthave it backed by LDAP, the obvious benefit being one could install off-the-shelf intranet tools inside one's organization butnot have to LDAP-enable them or create a parallel account system

The OpenID-LDAP Project (http://www.openid-ldap.org/) offers such a tool.
We're testing this on a Macintosh, but there seems to be no reason this won't work on any UNIX-y system.

Installation

First, download an unpack the code into the web server directory.

$ cd ~/Sites
$ curl --location 'http://www.openid-ldap.org/releases/openid-ldap-0.8.5-noarc.tar.gz' >openid-ldap-0.8.5-noarc.tar.gz
$ tar zxvf openid-ldap-0.8.5-noarc.tar.gz

This extracts the code into a non-versioned subdirectory called ‘openid-ldap'. It would be much better form if the directorywas called ‘openid-0.8.5'.

Interlude: Enabling PHP on Mac OS X Leopard

Leopard has PHP but it has to be explicitly enabled by editing configuration files (if you haven't enabled Apache on yourMac, see the links below)

     $ su -
     # cd /etc/apache2
     # vi httpd.conf
     remove the hash sign on the ‘LoadModule php5_module' line
     # apachectl restart

Here are some helpful links if you need more information:

Running to Stand Still

Without configuring anything, let's see what happens when we visit the page:

  • http://localhost/~davidjanes/openid-ldap/

Note that URL is Leopard's way of referencing a user's (i.e. "davidjanes") local webpage.

A webpage appears with a field for entering a username - but not a password. Entering a username - e.g. dpjanes - redirectsus to the 404 page:

  • http://localhost/~davidjanes/openid-ldap/dpjanes

... which definitely wasn't expected.

Reading through their documentation, it looks like they're mainly doing this using SSL/HTTPS and to do that one has to addsome rewrite rules to the Apache configuration. Since we're not doing that - at least not yet - we're probably using aninfrequently used code path, thus hitting a bug. Perusing the code we should see the URL above should be internally rewrittento:

  • http://localhost/~davidjanes/openid-ldap/index.php?user=dpjanes

To fix this we have modify the Apache configuration again. Changing ".htaccess" does not work because Apache on Leopard isconfigured "AllowOverride None" which means the rewrites will be ignored

$ su -
# cd /etc/apache2/users
# vi davidjanes.conf

And then we add the following:

     RewriteEngine On
     RewriteBase /~davidjanes/openid-ldap/
     RewriteCond %{REQUEST_URI} ^/.*[/]([a-z][-a-z0-9_]*)$
     RewriteRule ([A-Za-z0-9]+)$  /~davidjanes/openid-ldap/index.php?user=$1 [P]

And then

     # apachectl restart

Note that these rules are predicated on that we're going to be logging in using OpenID's "uid" which will be lower caseletters, numbers, dash or underscore.

Configuring LDAP

This is obviously the part where we're going to part paths - everyone does LDAP their own way. We don't have an ActiveDirectory setup here, but we do have VMWare Fusion (http://www.vmware.com/products/fusion/) and a JumpBox for OpenLDAPappliance (http://www.vmware.com/appliances/directory/1105) so it should be just a simple matter of figuring out the rightcombination of configuration settings.
The OpenID appliance has the following configuration:

  • JumpBox Name: openldap 0.9
  • Application Page: http://192.168.1.120/
  • Management Page: https://192.168.1.120:3000/

I've already configured a few accounts on this, but for example we have a user:

  • o=Directory
  • ou=users
  • cn=David Janes

In LDAP terms this gives us a "Distinguished Name" which is the really way LDAP (as I understand it) uniquely identifies arecord. In this particular case our Distinguished Name is "cn=David Janes,ou=users,o=Directory".
This user has the following configuration:

  • cn: David Janes
  • gidNumber: 1000
  • givenName: David
  • homeDirectory: /home/users/default/dpjanes
  • objectClass:
  • inetOrgPerson
  • posixAccount
  • top
  • sn: Janes
  • uid: dpjanes
  • uidNumber: 1000

We're going to use "uid" as the login ID - note that this is by no means a universal choice nor is it universally availableon all LDAP servers. I've seen LDAP servers use "name" to provide a unique identifier and it's possible - maybe even probably -that many LDAP servers don't provide short unique names at all.

Note then how LDAP logins should probably work:

  • one provides a part of the record we are looking for, for example "uid=dpjanes", where the user at login time provides the "dpjanes" part and the configured application prepends "uid="
  • given a starting point - the "searchdn" in the configuration below - we look for a matching record
  • when we have the matching record, we get the Distinguished Name which uniquely identifies a record and that we ask LDAP to validate it with a password

Note that OpenID-LDAP doesn't actually work quite this way; we'll explain this further down.

Configuring OpenID-LDAP to contact LDAP

Following, the instructions in openid-ldap/docs/README.txt, especially point (5) we get the key points of configuration -edit "ldap.php" and fill in the values.

The original connection settings look like this:

'primary'  => '10.0.0.111',
'fallback' => '10.0.0.222',
'protocol' => 3,
'binddn'   => 'cn=<name>,cn=users,dc=domain,dc=local',
'password' => '<pass>',
'searchdn' => 'cn=users,dc=domain,dc=local',
'filter'   => '(&(cn=%s)(mail=*))',
'testdn'   => 'cn=%s,cn=users,dc=domain,dc=local',
'nickname' => 'uid',
'email'    => 'mail',
'fullname' => array('givenName', 'sn'),
'country'  => 'c'

Our new connection settings look like this:

'primary'  => '192.168.1.120',
'fallback' => '',
'protocol' => 3,
'binddn'   => '',
'password' => '',
'searchdn' => 'ou=users,o=Directory',
'filter'   => 'uid=%s',
'testdn'   => 'uid=%s,ou=users,o=Directory',

Note the reasons for this:

  • primary: as per the VMWare notes above
  • fallback: we don't have a backup server
  • binddn & password: it works without this; but we assume there's LDAP configurations that require you to login with a well-known Distinguished Name and password before you can do a search
  • searchdn & filter: the ‘%s' is replaced with the user's login name (i.e. from the login form) and then these items are put together to search for the user's record
  • testdn: when actually logging in, the ‘%s' is replaced as above; the page then tests the modified testdn with the password provided against the server

Note then the difference between OpenID-LDAP and our hypothetical login scenario in the previous section - OpenID-LDAPsearches for the login but after validating that it exists, ignores the Distinguished Name and just tries to log in using asimply constructed testdn and password. This works, but it strikes me that the search is either unnecessary or the loginprocedure is insufficient.

Failure

Alas, at this point we're going to have to stop, unless someone has a suggestion. When I attempt to log in with "dpjanes" weend up with OpenID-LDAP bridge trying to log in with "uid=dpjanes,ou=users,o=Directory", which simply doesn't work. Whetherthis is specific to my LDAP implementation or not is unknown.

If I alter the rules so that I'm logging in with "David Janes" / "cn=David Janes,ou=users,o=Directory" the (slightlymodified) Apache rewrite rules get confused because of the space. I could probably fix these but quite frankly I don't want tobecause I want "dpjanes" to be recognized as the login.

So, that's as far as I'm getting with this. If anyone has further suggestions, please let me know and I'll modify thisdocument and necessary.

Comment #1jay_v

2009-02-17 22:31:55

Thanks for your post. It was a helpful starting point in installing OpenID-LDAP.

I thought I'd share our experiences to help others struggling with this install.

OpenID-LDAP is confusing because, as you mentioned, it doesn't work the way you expect. And since there's little overview you're not even sure what to do when you get lost. But fortunately, conceptually it is rather simple.

Here's how OpenID-LDAP works (not the OpenID part, just OpenID-LDAP itself). Once OpenID-LDAP is setup, you can go to the main page in your web browser. You enter & submit your username. OpenID-LDAP looks up the username via LDAP. If you're listed in the directory, you see your OpenID address along with a link at the bottom to login. Click "login" & OpenID-LDAP uses mod_rewrite to redirect your request back to the index page so you get a simple basic http authentication login prompt.

Problem is, you don't get any of this until EVERYTHING is setup which makes the install difficult. My advice, break this into some basic steps & build up.

First, you need https/SSL to make your login secure. Ideally, use one of your sites that you can already https to. Otherwise you have to setup https/SSL & that's a lot more work. (You probably already know this but OpenID-LDAP can reside within any of your domains, it doesn't need to be its own site/hostname. So if you have https://mySite.myDomain.com, you can install OpenID-LDAP in https://mySite.myDomain.com/openid/. But in our case we did opt to have a different hostname, https://openid.ourDomain.com.) Once you're secure, move on to LDAP.

(Your LDAP may be different than ours (we're using Open Directory on Mac OS 10.5), so this info may not be entirely accurate but will hopefully point you in the right direction.)

Make sure you search your LDAP directory. In your Terminal, issue something like:
    ldapsearch -x -h myLDAPHostName.myDomain.com -b uid=stevencolbert,cn=users,dc=myLDAPHostName,dc=myDomain,dc=com
(This basically says, "do an LDAP search for stevencolbert using your LDAP server myLDAPHostName.myDomain.com." Make sure you search for a known user in your directory & insert your LDAP server name accordingly.)

You want to make sure you're getting back a successful search result, "result: 0 Success". If you get something like "result: 32 No such object" then keep trying different values because OpenID-LDAP won't work if your LDAP settings are wrong.

OK, we can finally start setting up OpenID-LDAP.

Download & unzip as necessary. Then point your web browser to make sure you can reach the page. (For example, https://mySite.myDomain.com/openid/index.php.) If you can see the default OpenID-LDAP page then continue on. Otherwise you need to configure web server so you can see the page.

Edit the ldap.php file using your successful ldapsearch settings as a guide.

$GLOBALS['ldap'] = array (
        # Connection settings
'primary'               => 'myLDAPHostName.myDomain.com',  // Enter your LDAP server here, either by name or ip address.
'fallback'              => '',  // Enter your secondary LDAP server or just leave blank if you don't have a secondary.
'protocol'              => 3,
        # AD specific
'isad'                  => false, // are we connecting to Active Directory? Nope, we're using Open Directory.
'lookupcn'              => false, // should we extract CN after the search? Nah.
        # Binding account
'binddn'                => '',  // In our case we don't need one for simple lookups.
'password'              => '',  // In our case we don't need one for simple lookups.
        # User account
'testdn'                => 'uid=%s,cn=users,dc=myLDAPHostName,dc=myDomain,dc=com',   // NOTE: we use 'uid' instead of 'cn'!
        # Searching data
'searchdn'              => 'cn=users,dc=myLDAPHostName,dc=myDomain,dc=com',
'filter'                => 'uid=%s',  // Just a simple lookup for the username.


In your web browser enter your OpenID-LDAP URL but append "/index.php?user=aKnownUser". In our example, it would be https://mySite.myDomain.com/openid/index.php?user=stevencolbert.

If you followed each step above, you should see the "Your OpenID is" page showing a link with your OpenID, like https://mySite.myDomain.com/openid/stevencolbert.

Now you may be tempted to click the "Login" button (or you may be tempted go to your OpenID-LDAP home page & enter the username there). If you do you'll just get a "404 page not found" error. But that's ok, that's what the last step fixes.

The last step is to use mod_rewrite to properly redirect the URLs back to index.php. Without mod_rewrite, the URLs simply take the form "mySite.myDomain.com/openid/stevencolbert". Since there are no user folders (ie., no ./stevencolbert/index.html file) you get a "404 not found" error. Mod_rewrite takes the URL "mySite.myDomain.com/openid/stevencolbert" and changes it to "mySite.myDomain.com/openid/index.php?user=stevencolbert".

Add the following lines to your httpd.conf file. (Note: If you're using Mac OS 10.5 Server, it uses Apache2 & stores the file in /etc/apache2/sites/  (for example, /etc/apache2/sites/0019_any_443_mySite.myDomain.com.conf).

        <IfModule mod_rewrite.c>
                RewriteCond %{REQUEST_URI}         !^/(.+)\.php(.*)$
                RewriteRule ^/([A-Za-z0-9]+)$ https://mySite.myDomain.com/openid/index.php?user=$1

                RewriteCond %{REQUEST_URI}      !^/(.+)\.php(.*)$
                RewriteCond %{THE_REQUEST}      ^[A-Z]{3,9}\ /dir/([A-Za-z0-9]+)\?(.*)\ HTTP/
                RewriteRule ^(.*)$        https://mySite.myDomain.com/openid/index.php?user=%1&%2
        </IfModule>

In your Terminal, restart apache with
  apachectl graceful

Now you can (finally!) go to https://mySite.myDomain.com/openid, submit your username, click "Login" & authenticate. Finished!


One last tip. If you want to logout, you can append the URL with "?user=yourUserName&openid_mode=logout". For example, "https://mySite.myDomain.com/openid/index.php?user= stevencolbert&openid_mode=logout".

Good luck!

Add Comment