from gluon.validators import IS_EMAIL
if ldap_mode == 'ad':
# Microsoft Active Directory
if IS_EMAIL()(username)[1] is not None:
#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))
else:
return False
username_bare = username.split("@")[0]
This prevent login to occure and new user to be inserted when email is used
as username... however it not returning any advise to the user... I will
try to figure out how to implement validation from ldap_auth and get back
with a patch.
Richard
On Wed, Aug 7, 2013 at 10:56 AM, Richard Vézina <[email protected]
> wrote:
> Ok!
>
> :)
>
> Richard
>
>
> On Wed, Aug 7, 2013 at 10:10 AM, Massimo Di Pierro <
> [email protected]> wrote:
>
>> Please send me a patch when you test it. ;-)
>>
>> On Wednesday, 7 August 2013 07:51:58 UTC-5, Richard wrote:
>>
>>> No change... Auth seems to delegate entirely the validation on username
>>> input field in case ldap_auth is used as authentication method.
>>>
>>> I guess this simple refactor (not tested) could do the tricks at least
>>> for Active directory :
>>>
>>> if not IS_EMAIL()(username)[1]:
>>> domain = []
>>> for x in ldap_basedn.split(','):
>>> if "DC=" in x.upper():
>>> domain.append(x.split('=')[-1]**)
>>> identifier = "%s@%s" % (username, '.'.join(domain))
>>> else: return ERROR...
>>> username_bare = username.split("@")[0]
>>>
>>> Richard
>>>
>>>
>>>
>>> On Wed, Aug 7, 2013 at 8:42 AM, Richard Vézina <[email protected]>wrote:
>>>
>>>> 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<http://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=**Tr**ue)
>>>>>>
>>>>>> 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 web2py+un...@**googlegroups.com.
>>>>>
>>>>> For more options, visit
>>>>> https://groups.google.com/**groups/opt_out<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.
>>
>>
>>
>
>
--
---
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.