The next BugTracker.NET releases will include some LDAP support, as well as support for its window's incarnation, Active Directory. LDAP is a new technology for me. It wasn't clear to me how to get started learning it. With a new programming language, there's always a "Hello World" tutorial for getting started but I had trouble finding a "Hello World" style tutorial for LDAP, targeted to somebody who needed an introduction to even basic LDAP concepts, like "distinguished name". I was able to get OpenLDAP up and running but for a while I didn't know what to do with it. I didn't know what to put in an LDIF file - I didn't understand that I was defining both the schema and data at the same time with the LDIF. But eventually a few things clicked and I got it. Now that I know a little bit more, I think these are the resources that WOULD have been helpful had I been lucky enough to have stumbled upon them when I needed them, which I wasn't:
http://www.ldapman.org/articles/intro_to_ldap.html
http://www.umich.edu/~dirsvcs/ldap/doc/guides/slapd/1.html
http://www.redbooks.ibm.com/redbooks/SG244986/wwhelp/wwhimpl/java/html/wwhelp.htm
What is LDAP support, concretely? What does it mean that BugTracker.NET supports LDAP? A first step - my first step - is to check users' passwords against the ones stored in the LDAP directory instead of the ones stored in the database, so that passwords can be the same across applications. The next step would be automatic user creation. That is, for BugTracker.NET to work - for just about any tracker to work - there needs to be a row in the tracker's database for that user. It's not enough that the user exists in the LDAP directory, it also needs to exist in the database. So, what a tracker can do, if a user/password combo is authenticated against LDAP, is create the database row the first time the user logs into the tracker. The tracker could either create a bare bones user, with default characteristics, or the tracker could use some attributes from LDAP to set the corresponding attributes in the tracker db. For example, there could be an attribute in the LDAP directory that BugTracker.NET should intrepet as corresonding to the corresponding BugTracker.NET "organization" of a user. Another way of using LDAP is to create a tool that allows admins to do an initial mass import of users.
I did my testing using OpenLDAP only. I knew there needed to be a way for others to set specify configuration settings different from mine. For my first step, these were the items I knew enough to allow the admin to configure in Web.config:
<add key="AuthenticateUsingLdap" value="1"/> <!-- a switch for turning LDAP integration on/off -->
<add key="LdapServer" value="127.0.0.1"/>
<add key="LdapUserDistinguishedName" value="uid=$REPLACE_WITH_USERNAME$,ou=people,dc=mycompany,dc=com"/> <!-- a template for the distinguished name -->
And here's the code. I didn't allow "AuthType" to be configurable, because I didn't know if it matters in the real world. I don't have any experience to know.
public static bool check_password_with_ldap(string username, string password)
{
string dn = btnet.Util.get_setting(
"LdapUserDistinguishedName",
"");
string ldap_server = btnet.Util.get_setting(
"LdapServer",
"127.0.0.1");
dn = dn.Replace("$REPLACE_WITH_USERNAME$", username);
LdapConnection ldap = new LdapConnection(ldap_server);
System.Net.NetworkCredential cred = new System.Net.NetworkCredential(dn, password);
ldap.AuthType = AuthType.Basic;
bool bResult = false;
try
{
ldap.Bind(cred);
btnet.Util.write_to_log("LDAP authentication ok: " + username);
return true;
}
catch (LdapException e)
{
string s = e.Message;
if (e.InnerException != null)
{
s += "\n";
s += e.InnerException.Message;
}
// write the message to the log
btnet.Util.write_to_log("LDAP authentication failed: " + s);
return false;
}
}
Does the code above look reasonable? I hope so.
Something I should have done right up front was to take a look at the LDAP documentation of some of the other BugTrackers, like
Jira,
FogBugz,
Bugzilla. When I did finally look at how other applications were handling it, I
found the most detailed concrete information from Jira, especially just
this screenshot below. I guess everything there is there for a reason,
so I can see that I will have to add more configurability in the future.
But, I have to crawl before I can walk, so I'll release what I have
this weekend and then see what kind of feedback and code contributions I get.