It's not exactly obvious how LDAP authentication is supposed to work in FogBugz, but here's an explanation of what happens:
- It takes the "username" the user supplied, and substitutes that into the DN template given as "sLDAPCustomUserTemplate".
- It then binds (ie, logs into) the LDAP server given as "sLDAPCustomURL" - so if you said "ldap://ldap.example.com/dc=example,dc=com", it'll log into ldap.example.com. I've cheerfully no idea if it handles "ldaps" URIs, or tries enabling TLS at all. In case you wonder, this is a "Simple Bind", rather than SASL.
- Assuming this works, it then performs a subtree search with a base DN given as the path in "sLDAPCustomURL" - using the filter given as "sLDAPCustomValidateFilter" - again, with the username substituted in.
- It take the first match from that search and copies the results into the Person SQL table, populating the results. If you get no results from this search (done, remember, as the user), then the user is rejected, which is how you can make groups work.
Now, this obviously fails in a number of cases - like if your users aren't in a single, flat part of the DIT, or if the attribute you really want users to be logging in as their username with isn't the naming attribute (and so isn't a part of the DN). What we really need is for the search to run first, and the bind use the results.
Most critically, if the search run in step 3 returns more than one match, things can go badly wrong. (You can, for example, collide two users together, which takes SQL knowledge to sort out).
So we have:
o=Isode
ou=Staff
cn=Dave Cridland
My Custom LDAP URI is just "ldap://ldap.isode.com/" - I don't need a base DN here.
My User Template is "cn=^USER,ou=Staff,o=Isode". So logging in as "Dave Cridland" will work.
My Validate Filter is "(&(objectClass=inetOrgPerson)(cn=^USER))".
The rest are obvious.
When I log in, this does the equivalent, in terms of the OpenLDAP tools, of:
ldapsearch -H 'ldap://ldap.isode.com/' -x -W -D 'cn=Dave Cridland,ou=Staff,o=Isode' '(&(objectClass=inetOrgPerson)(cn=Dave Cridland))' displayName telephoneNumber mail
And then locates and populates my Person row according to the first result found.
Or in more general terms:
Assuming we split the URL option such that ${sLDAPCustomURL} = ${sLDAPCustomURL_Root}${sLDAPCustomURL_BaseDN}
ldapsearch -H ${LDAPCustomURL_Root} -x -W -D ${sLDAPCustomUserTemplate} -b ${sLDAPCustomURL_BaseDN} ${sCustomLDAPValidateFilter} ${sLDAPCustom*Attribute}