Hello,
I was about to post this (I think I answer your question) :
Hello,
I think I found a flaw in the interaction between Auth and LDAP contrib
(web2py 2.4.7).
If I set LDAP as unique authentification method
(auth.settings.login_methods = LDAP) as written in the book, web2py should
leaves LDAP to create user... The things is web2py Auth seems to create
user even if it LDAP that is responsible of doing it. I mean, I carefully
read the code of LDAP and the only way it could create a new user is if
manage_groups=True by calling do_manage_groups() since the other place
where LDAP is instert new user it set email, first_name and last_name. In
my case, if user use email instead of username (that should not be email,
but I can't enforce this with the custom IS_NOT_EMAIL() validator I wrote)
for login a new user get inserted like this : first_name = email (or the
content of username input that is an email), username = email and
registration_id = email. As far as I can see the only way LDAP could
produce this result is if the do_manage_groups method is called, but it
can't be call if manage_groups is set to False. So, the only remaining
possibility is that Auth is creating the new user because it recieve a bad
signal from LDAP.
I make a couples tests and found that the insert new user base on the
credentials of already existing user that log with it email instead of it
username occure at line 2147-2148. So I guess Auth recieve a True flag from
LDAP mean the user exist in directory, since web2py can't match a existing
user base on the wrong username (email) it insert a new user with wrong
setting.
The origin of this is multifold. First, I think it could be prevent if
there was a IS_NOT_EMAIL() validator on the username field, for some reason
I can't get it to work properly with LDAP because of the way LDAP is
working the validator seems to be skipped, and the username is first check
against directory. Maybe using IS_NOT_EMAIL() inside ldap_auth contrib
could solve this issue. Other possible origin is the way ldap_auth is
written. I mean it seems that for saving a variable "username" is
re-used... I think that the issue is coming from line 8 of code extract
below :
if ldap_mode == 'ad':
# Microsoft Active Directory
if '@' not in username:
domain = []
for x in ldap_basedn.split(','):
if "DC=" in x.upper():
domain.append(x.split('=')[-1])
username = "%s@%s" % (username, '.'.join(domain))
username_bare = username.split("@")[0]
con.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
# In cases where ForestDnsZones and DomainDnsZones are
found,
# result will look like the following:
# ['ldap://ForestDnsZones.domain.com/DC=ForestDnsZones,
# DC=domain,DC=com']
if ldap_binddn:
# need to search directory with an admin account 1st
con.simple_bind_s(ldap_binddn, ldap_bindpw)
else:
# credentials should be in the form of
[email protected]
con.simple_bind_s(username, password)
# this will throw an index error if the account is not found
# in the ldap_basedn
requested_attrs = ['sAMAccountName']
if manage_user:
requested_attrs.extend([user_firstname_attrib,
user_lastname_attrib,
user_mail_attrib])
result = con.search_ext_s(
ldap_basedn, ldap.SCOPE_SUBTREE,
"(&(sAMAccountName=%s)(%s))" % (
ldap.filter.escape_filter_chars(username_bare),
filterstr),
requested_attrs)[0][1]
if not isinstance(result, dict):
# result should be a dict in the form
# {'sAMAccountName': [username_bare]}
logger.warning('User [%s] not found!' % username)
return False
if ldap_binddn:
# We know the user exists & is in the correct OU
# so now we just check the password
con.simple_bind_s(username, password)
username = username_bare
This peace of code is pretty unreliable : It start by re-creating a email
and store it in username vars if username it recieves from web2py is not a
email before derive a username_bare from the altered username var and at
the end it finally set username = username_bare... Why all this just to
avoid create a var?!
I propose to refator this using creating a new ID or identifier var to
store connection "identifier" var instead reusing the username for that.
Then it will require to determine if the IS_NOT_EMAIL() should go at Auth
level or ldap_auth. I don't know so much LDAP in general and even less the
different implementation, so I don't know if some implementation use email
as an identifier or not. Since, the Auth class as mechanism to create
missing user I don't no if it intentional to allow the creation of user
with email as username or not... So, maybe it a option in to use
IS_NOT_EMAIL() on username field in this case it will require that
IS_NOT_EMAIL be at level of Auth. Maybe, I didn't be able to make work my
custom validator because of the order of validator (I had set multiple
validator on username), I will try to set only IS_NOT_EMAIL and report here
if it solve the problem I have with LDAP authentication.
Thanks
Richard
On Wed, Aug 7, 2013 at 7:22 AM, Massimo Di Pierro <
[email protected]> wrote:
> How would you change this?
>
>
> On Monday, 5 August 2013 15:42:39 UTC-5, Richard wrote:
>
>> Hello,
>>
>> Is there a way to prevent user to log with there email? I set LDAP
>> authentication, I create a username field on custom auth_user model and set
>> auth.define_tables(username=**True)
>>
>> But I notice that I can still login with [email protected]. In this case,
>> ldap_auth create a new user with first_name and username =
>> [email protected]
>>
>> So, I think there is a flaw here in ldap_auth :
>>
>> if ldap_mode == 'ad':
>> # Microsoft Active Directory
>> if '@' not in username:
>> domain = []
>> for x in ldap_basedn.split(','):
>> if "DC=" in x.upper():
>> domain.append(x.split('=')[-1]**)
>> username = "%s@%s" % (username, '.'.join(domain))
>> username_bare = username.split("@")[0]
>>
>> Since it seems to recreate email as username...
>>
>> Thanks
>>
>> Richard
>>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "web2py-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
>
--
---
You received this message because you are subscribed to the Google Groups
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.