LDAP: Support for user search by "uid" instead of "dn"
Feature-Request
Hi.
First of all: Thank you for this super helpful tool.
Here an idea for a new feature regarding LDAP authentication:
Introduction
Authentication works perfectly by using the cn from the DN, e.g.:
cn=My Username,ou=users,dc=example,dc=com
with the related config part:
"username_pattern": "cn=$username,ou=users,dc=example,dc=com",
So: My Username can be used to login.
Feature Request
In my case, the existing directory tree can not be changed (easily), but it would be nice if users can use their "uid" to login, instead of their full name.
A possible way would be:
- create a config parameter to use the uid (or another attribute, which can be used to search for the dn)
- use the bind-dn to search for the uid with the given base-dn
- if it occurs only once: use the determined dn to login
- try to (simple-)bind with that dn and the given user password
Thanks in advance.
Greetings, HomerJay
Hi @jayjensen thanks for the suggestions! Do users know their uids?
They can also use the full dn to login, potentially.
Hi @bugy
Thank you for the super-quick reply!
The standard-way for us, with other tools, is to use the uid and not their full name. So it would need some explanation, if they need to use their full name with your scriptserver.
Bests regards, HomerJay
I see, thanks! Do you want/can create a PR for it? :)
Thanks again.
I would like to, but I am afraid, that my programming skills are not good enough.
Best regards, HomerJay
My main concern with this approach is that we would need to store "admin" (or global user search access) password in script server config. Would it be fine?
I understand. This is an important security point.
The bind-user (config settings: "client_id" and "secret"), which is used to get the group memberships, should be enough, if the bind-user has the needed permissions, configured on the LDAP server.
Side note: Typically, the bind-user should only have the minimum permissions, which are required. So this should never be a user with admin-permissions.
Sorry, after looking at the source code (again), it seems that I understood something wrong. These config-settings ("client_id" and "secret") do not seem to be related to LDAP.
It's not about group membership. Script server would need to connect to a LDAP server, in order to perform the following steps:
- use the bind-dn to search for the uid with the given base-dn
- if it occurs only once: use the determined dn to login
Hello again, yes, I understand, I should have been more precise.
The config example for LDAP, which I tested with, contained client_id and secret, which seem to be wrong.
Anyways: I made my first pull request on GitHub, regarding this feature request. Please note, that my programming skills are quite basic ;)
Have a nice day.
Greetings, HomerJay
Hi @jayjensen thanks for your PR! I liked it, but wanted to do slightly different configuration structure and use this opportunity to refactor LdapAuthenticator class. I also wanted to test claude code, on how useful would it be (actually not that much when I needed smarter refactoring)
I used your code as a reference on how to read user by uid, so it was definitely helpful.
Would you be able to test this build and let me know if it works?
Hi @bugy
Thank you very much! I am glad, that my code was helpful in some way.
I will test it as soon as possible (hopefully at the weekend).
Thanks again and have a nice day.
Greetings, HomerJay
Hi again @bugy
It took a while until I recognized, that I have to define a dictionary within the "auth" part of the conf.json (server-config), but now I can login by the searched uid.
config-snippet (example):
`
"auth": ...
...
"ldap_user_resolver": {
"search_by_attribute": "uid",
"admin_user": "cn=bind_user,dc=example,dc=com",
"admin_password": "a_funky_passwd"
} `
Additional testing: Alternatively, I can also log in by the cn, e.g. with the following alternative config, without search attribute (example):
`
"auth":
... "ldap_user_resolver": { "username_pattern": "cn=$username,ou=users,dc=example,dc=com", } ... `
Amazing, thank you.
Important: When I do not put the related config-parts in the ldap_user_resolver config dictionary, there occurs a problem:
Within:
LdapUserResolver class,
the exception is not raised for:
if not username_pattern and not search_by_attribute:
...
and I get to the "else" block of:
def resolve_ldap_username(self, username, base_dn):
...
else:
return username
So this would break existing configs which use ldap auth.
Greetings, HomerJay
I forgot to mention, that I tested with OpenLDAP and I have no possibility to test on related systems, for example ActiveDirectory.
Hi @jayjensen thanks a lot for testing and feedback I'm sorry, that i forgot to mention about config
Regarding your concern about putting username_pattern under the resolver. This is expected: i created a migration script, which is executed once on server startup, which moves the username pattern under resolver. I don't like keeping backward compatible changes, which i can avoid by a simple migration :)