Opened 14 years ago
Closed 12 years ago
#7999 closed enhancement (fixed)
LDAP bind using login creds
Reported by: | Owned by: | branson | |
---|---|---|---|
Priority: | normal | Component: | DirectoryAuthPlugin |
Severity: | normal | Keywords: | |
Cc: | Trac Release: | 0.12 |
Description
Nice plugin, thanks for writing it.
I was wondering if it's possible to bind to the ldap server using the login username/password and using that as the test for successful authentication. One other question then pops up, if we bind this way will we still be able to get the person's real name and email address to populate the session_attribute table?
Attachments (0)
Change History (7)
comment:1 Changed 14 years ago by
Priority: | normal → low |
---|---|
Status: | new → assigned |
comment:2 follow-up: 3 Changed 14 years ago by
I think I follow what you're saying. To perform auth:
- You bind using bind_dn and do a search for the login name to get the DN.
- You bind again, using the located DN and login password.
I'm not a python guy, but i am a perl guy. There is a class, Authen::Simple::ActiveDirectory, which does auth via AD, but does not require the same bind_dn account info that this plugin requires. Looking at the perl code they bind using the string 'username@domain' and login password. The host it binds to is the domain name itself.
So bind( username@…, password ) to the server example.com.
So, in this way, can your plugin attempt to bind as the users's principal and avoid a separate bind account? If so, then I wonder if you're still able to look up attributes such as real name and password.
I'll try to have a look at your code and see if I can make this change. Not a python or LDAP guy but I would love to get this working for Trac!
comment:3 follow-up: 5 Changed 14 years ago by
Priority: | low → normal |
---|
Replying to spohail:
I think I follow what you're saying. To perform auth:
- You bind using bind_dn and do a search for the login name to get the DN.
- You bind again, using the located DN and login password.
Exactly
So bind( username@…, password ) to the server example.com.
Apparently, that also works. This is what I get for misunderstanding the documentation. I realize now that there is a slight difference between binding and authenticating. When binding using the full dn, it forces authentication using that object. However, once can also simply authenticate using the username@domain, and, if I read it correctly, domain\username should work also.
So, in this way, can your plugin attempt to bind as the users's principal and avoid a separate bind account? If so, then I wonder if you're still able to look up attributes such as real name and password.
In order to get full name, and email address we will still have to do a search and bind, but we should be able to do that with the authentication of the user.
I'll try to have a look at your code and see if I can make this change. Not a python or LDAP guy but I would love to get this working for Trac!
So, if you still feel inclined, you're more than welcome to try to make a patch. I will also try to find some time to adjust the code to make this possible. Thanks for helping me learn something.
comment:4 Changed 14 years ago by
Off the bat, for performance sake, I replaced _get_user_dn()
with:
def _get_user_dn(self, user): return '%s@%s' % ( user, self.ads );
I messed around with this for quite a while, and best I can tell, unless you mangle the existing functionality or store login passwords for retrieval later, there's no clean way around having the extra account. Not a big deal though, I can work with it as is. The only thing I would change is upon login, update the session_attributes table with the current email/full name values from LDAP in case a) the user wasn't in LDAP the last time /admin/accounts/users
was hit or b) this info changed.
Between this plugin, FlexibleAssignToPlugin, and this patch, I have everything I need.
comment:5 Changed 13 years ago by
Replying to pacopablo:
Replying to spohail:
So bind( username@…, password ) to the server example.com.
Apparently, that also works. This is what I get for misunderstanding the documentation. I realize now that there is a slight difference between binding and authenticating. When binding using the full dn, it forces authentication using that object. However, once can also simply authenticate using the username@domain, and, if I read it correctly, domain\username should work also.
I've been experimenting a bit on what is needed to bind. These are the conclusions regarding the strings I tried for bind_dn
:
- using my
distinguishedName
fails to bind - using my
mail
attribute fails to bind - using my
sAMAccountName
attribute fails to bind - using my
userPrincipalName
binding succeeds. The value of this attribute is formatted as an email address but different frommail
. - using the
/o
and/cn
of thelegacyExchangeDN
in adomain\username
binding succeeds. The/cn
is identical to mysAMAccountName
. - same when using the information from
msExchADCGlobalNames
- in all cases, case is irrelevant
I should add that we have had a domain name change. My mail
attribute uses the new domain name, but the userPrincipalName
still uses the old domain name. This value also uses my sAMAccountName
as the username part.
Hope this helps.
comment:6 Changed 12 years ago by
Owner: | changed from John Hampton to branson |
---|---|
Status: | assigned → new |
So some points here:
- AD does not allow anonymous bind unless the registry is hacked. SO not sure that allowing search via anonymous is valid.
- if we tried to use the user/pass of the current user, we'd have to cache that password somewhere locally using reversable encryption. This is a Bad Idea(tm) from a security POV.
- you can use {user}@{realm} in some cases.. and we could flag to support that as the username if you wanted. Might even be able to extend to validate against multiple realms that way. Would take some coding, and I dont' have a multi-realm AD config to test with ;-)
- it's fairly trivial to setup a non-priv'd user for AD ( cn=search,cn=users,dc=ad,dc=com ) to perform searches .. but no logins.
comment:7 Changed 12 years ago by
Resolution: | → fixed |
---|---|
Status: | new → closed |
So .. I have fixed several things on this that you might find useful:
- Renamed the plugin to DirectoryAuthPlugin
- Now can do anonymous and SSL based bind.
- Name and email are now populating to the session table.. and you can select the vars that are used
I am gonna close this as I think it's fixed now. If you find trouble .. please open a new ticket.
So, I think I understand your question. I'll go with a long explanation and you can tell me that I misunderstood everything later.
The plugin does bind to the AD server using the creds supplied by the user logging into Trac. In fact, this is the only way that I know of to actually check whether or not they typed in the correct password.
That being said, I think you're interested in getting rid of the need to specify the
bind_dn
andbind_passwd
options in thetrac.ini
Obviously, it would require a code change to remove the need for
bind_dn
andbind_passwd
. However, that's not to say it can't be done.The bigger problem is in mapping usernames to DNs. To bind to AD, one needs a DN in the form of:
Rarely, however, do the login name (
sAMAccountName
attribute) and thecn
portion match. A method for mappingsAMAccountName
to DN would be needed. However, it may not be possible. For instance, in my organization,sAMAccountName
s are first initial, middle initial, lastname. Thecn
, however, is the full name with the middle initial. There is no way to map fromsAMAccountName
to DN. Because of this, we bind as a known user,bind_dn
, and then look for thesAMAccountName
.If we allow anonymous queries to AD (not the default as far as I am aware), then we could do the search for
sAMAccountName
without usingbind_dn
If you have other suggestions, or perhaps even a patch, I'd be happy to consider them. I don't have an environment where I can play around with anonymous binds, so, without a patch, I'm not sure how quickly this will be implemented.