diff --git a/bt5/erp5_user_tutorial_ui_test/SkinTemplateItem/portal_skins/erp5_user_tutorial_ui_test/Zuite_createAnotherFunctionalTestUser.py b/bt5/erp5_user_tutorial_ui_test/SkinTemplateItem/portal_skins/erp5_user_tutorial_ui_test/Zuite_createAnotherFunctionalTestUser.py
index ff23827f837819227ad106cc0a56c317912453da..3ced38c273142f2da9118e90192c08ddb9820a2c 100644
--- a/bt5/erp5_user_tutorial_ui_test/SkinTemplateItem/portal_skins/erp5_user_tutorial_ui_test/Zuite_createAnotherFunctionalTestUser.py
+++ b/bt5/erp5_user_tutorial_ui_test/SkinTemplateItem/portal_skins/erp5_user_tutorial_ui_test/Zuite_createAnotherFunctionalTestUser.py
@@ -12,7 +12,6 @@ if person is None:
                                            title=functional_test_username)
 
   person.edit(reference=functional_test_username,
-              password=howto_dict['functional_test_user_password'],
               default_email_text=howto_dict['functional_test_user_email'])
 
   person.validate()
@@ -23,6 +22,13 @@ if person is None:
                                  function='company/manager')
   assignment.open()
 
+  login = person.newContent(
+    portal_type='ERP5 Login',
+    reference=functional_test_username,
+    password=howto_dict['functional_test_user_password'],
+  )
+  login.validate()
+
   # XXX (lucas): These tests must be able to run on an instance without security.
   for role in ('Assignee', 'Assignor', 'Associate', 'Auditor', 'Owner'):
     portal.acl_users.zodb_roles.assignRoleToPrincipal(role, person.Person_getUserId())
diff --git a/bt5/erp5_user_tutorial_ui_test/SkinTemplateItem/portal_skins/erp5_user_tutorial_ui_test/Zuite_createFunctionalTestUser.py b/bt5/erp5_user_tutorial_ui_test/SkinTemplateItem/portal_skins/erp5_user_tutorial_ui_test/Zuite_createFunctionalTestUser.py
index 6fd394047b2b35cada1a704dca44936cce28a873..0fb0822b78b2f1bd098c21e1c2ac44a9903bbf37 100644
--- a/bt5/erp5_user_tutorial_ui_test/SkinTemplateItem/portal_skins/erp5_user_tutorial_ui_test/Zuite_createFunctionalTestUser.py
+++ b/bt5/erp5_user_tutorial_ui_test/SkinTemplateItem/portal_skins/erp5_user_tutorial_ui_test/Zuite_createFunctionalTestUser.py
@@ -12,7 +12,6 @@ if person is None:
                                            title=functional_test_username)
 
   person.edit(reference=functional_test_username,
-              password=howto_dict['functional_test_user_password'],
               default_email_text=howto_dict['functional_test_user_email'])
 
   person.validate()
@@ -23,6 +22,13 @@ if person is None:
                                  function='company/manager')
   assignment.open()
 
+  login = person.newContent(
+    portal_type='ERP5 Login',
+    reference=functional_test_username,
+    password=howto_dict['functional_test_user_password'],
+  )
+  login.validate()
+
   # XXX (lucas): These tests must be able to run on an instance without security.
   for role in ('Assignee', 'Assignor', 'Associate', 'Auditor', 'Owner'):
     portal.acl_users.zodb_roles.assignRoleToPrincipal(role, person.Person_getUserId())
diff --git a/bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/ERP5Site_createPersonToAskAccountRecover.py b/bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/ERP5Site_createPersonToAskAccountRecover.py
index e9e03ccc5fda8d117390fbe663914770ea1068d8..1c0a322359cf595891780e703a72a0fcd5d2290c 100644
--- a/bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/ERP5Site_createPersonToAskAccountRecover.py
+++ b/bt5/erp5_web_renderjs_ui_test/SkinTemplateItem/portal_skins/erp5_web_renderjs_ui_test/ERP5Site_createPersonToAskAccountRecover.py
@@ -11,10 +11,15 @@ else:
   person = person_module.newContent(portal_type="Person",
                                     reference=user_id,
                                     id=user_id,
-                                    password=new_password,
                                     default_email_text="userA@example.invalid")
   assignment = person.newContent(portal_type='Assignment')
   assignment.open()
+  login = person.newContent(
+    portal_type='ERP5 Login',
+    reference=user_id,
+    password=new_password,
+  )
+  login.validate()
 
 # Make sure always a new password
 person.setPassword(new_password)
diff --git a/bt5/erp5_web_ui_test/SkinTemplateItem/portal_skins/erp5_web_ui_test/WebSiteModule_resetWebZuite.py b/bt5/erp5_web_ui_test/SkinTemplateItem/portal_skins/erp5_web_ui_test/WebSiteModule_resetWebZuite.py
index df314e03f7db7e9f909091695d594b13a3a15f4f..570a75ffd9a979717ff53c89066d53727ac3db31 100644
--- a/bt5/erp5_web_ui_test/SkinTemplateItem/portal_skins/erp5_web_ui_test/WebSiteModule_resetWebZuite.py
+++ b/bt5/erp5_web_ui_test/SkinTemplateItem/portal_skins/erp5_web_ui_test/WebSiteModule_resetWebZuite.py
@@ -27,7 +27,7 @@ if not portal.person_module.has_key('test_webmaster'):
 else:
   person = portal.person_module.test_webmaster
 person.edit(first_name='Test', last_name='Webmaster',
-            reference='test_webmaster', password='test_webmaster')
+            reference='test_webmaster')
 person.setRole('internal')
 if not len(person.objectValues(portal_type='Assignment')):
   assignment = person.newContent(portal_type='Assignment')
@@ -36,6 +36,13 @@ if not len(person.objectValues(portal_type='Assignment')):
                   stop_date=DateTime('2990/12/31'))
   if assignment.getValidationState() != 'open':
     assignment.open()
+if not len(person.objectValues(portal_type='ERP5 Login')):
+  login = person.newContent(
+    portal_type='ERP5 Login',
+    reference='test_webmaster',
+    password='test_webmaster',
+  )
+  login.validate()
 if person.getValidationState() != 'validated':
   person.validate()
 
diff --git a/bt5/erp5_web_ung_role/TestTemplateItem/portal_components/test.erp5.testUNGSecurity.py b/bt5/erp5_web_ung_role/TestTemplateItem/portal_components/test.erp5.testUNGSecurity.py
index c45bf38b3a7cf160d68b287da0cd5e5c22ebdd06..8af8c9536a98c3daaeb7a0882101c1120b90ee5d 100644
--- a/bt5/erp5_web_ung_role/TestTemplateItem/portal_components/test.erp5.testUNGSecurity.py
+++ b/bt5/erp5_web_ung_role/TestTemplateItem/portal_components/test.erp5.testUNGSecurity.py
@@ -51,6 +51,11 @@ class TestUNGSecurity(ERP5TypeTestCase):
     assignment = person.newContent(portal_type='Assignment')
     assignment.setFunction("function/ung_user")
     assignment.open()
+    login = person.newContent(
+      portal_type='ERP5 Login',
+      reference='ung_user',
+    )
+    login.validate()
     self.tic()
 
   def testERP5Site_createNewWebDocumentAsAnonymous(self):
@@ -82,6 +87,11 @@ class TestUNGSecurity(ERP5TypeTestCase):
     assignment = person.newContent(portal_type='Assignment')
     assignment.setFunction("function/ung_user")
     assignment.open()
+    login = person.newContent(
+      portal_type='ERP5 Login',
+      reference='ung_user2',
+    )
+    login.validate()
     self.tic()
     self.loginByUserName("ung_user")
     self.changeSkin("UNGDoc")
@@ -175,6 +185,11 @@ class TestUNGSecurity(ERP5TypeTestCase):
     assignment = person.newContent(portal_type='Assignment')
     assignment.setFunction("function/ung_user")
     assignment.open()
+    login = person.newContent(
+      portal_type='ERP5 Login',
+      reference='ung_user2',
+    )
+    login.validate()
     self.tic()
     self.loginByUserName("ung_user")
     self.changeSkin("UNGDoc")
diff --git a/bt5/erp5_web_ung_theme/TestTemplateItem/portal_components/test.erp5.testUNG.py b/bt5/erp5_web_ung_theme/TestTemplateItem/portal_components/test.erp5.testUNG.py
index a42969b17855fc6c4ba1c979b5ab093410cb098c..f36efe88321b30d43f37139adf36e6b70ba6fcf7 100644
--- a/bt5/erp5_web_ung_theme/TestTemplateItem/portal_components/test.erp5.testUNG.py
+++ b/bt5/erp5_web_ung_theme/TestTemplateItem/portal_components/test.erp5.testUNG.py
@@ -133,10 +133,12 @@ class TestUNG(ERP5TypeTestCase):
                                              reference="ung_new_user")
     assignment = person.newContent(portal_type='Assignment')
     assignment.open()
+    person.newContent(portal_type='ERP5 Login', reference=person.getReference()).validate()
     person = portal.person_module.newContent(portal_type='Person',
                                              reference="ung_new_user2")
     assignment = person.newContent(portal_type='Assignment')
     assignment.open()
+    person.newContent(portal_type='ERP5 Login', reference=person.getReference()).validate()
     self.tic()
     self.loginByUserName("ung_new_user")
     self.changeSkin("UNGDoc")
diff --git a/bt5/networkcache_erp5/TestTemplateItem/portal_components/test.erp5.ShaSecurityMixin.py b/bt5/networkcache_erp5/TestTemplateItem/portal_components/test.erp5.ShaSecurityMixin.py
index 02261c0fdf01f693086c934206437526f91363c2..6fda60576a9cffae61b7b134dfd7f6a9c67007b3 100644
--- a/bt5/networkcache_erp5/TestTemplateItem/portal_components/test.erp5.ShaSecurityMixin.py
+++ b/bt5/networkcache_erp5/TestTemplateItem/portal_components/test.erp5.ShaSecurityMixin.py
@@ -52,8 +52,13 @@ class ShaSecurityMixin(object):
     if person is None:
       person = self.portal.person_module.newContent(portal_type='Person')
       person.edit(first_name=reference,
-                  reference=reference,
-                  password=password)
+                  reference=reference)
+      login = person.newContent(
+        portal_type='ERP5 Login',
+        reference=reference,
+        password=password,
+      )
+      login.validate()
       self.tic()
 
     create = True
diff --git a/product/ERP5/tests/testAccounting_l10n_fr.py b/product/ERP5/tests/testAccounting_l10n_fr.py
index 7b76f9a45b247b573162b4392e97878d8d199049..7f8feb25d1734133eb90881cedee1c9edf0f3bea 100644
--- a/product/ERP5/tests/testAccounting_l10n_fr.py
+++ b/product/ERP5/tests/testAccounting_l10n_fr.py
@@ -82,6 +82,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
                                         default_email_text=self.recipient_email_address)
       assignment = person.newContent(portal_type='Assignment')
       assignment.open()
+      person.newContent(portal_type='ERP5 Login', reference=self.username).validate()
     self.tic()
 
     uf = self.portal.acl_users
diff --git a/product/ERP5/tests/testBug.py b/product/ERP5/tests/testBug.py
index aa942a5749ef1842637ed79827b99f3f57f9cbb6..cc46efa80b09d0a34efdace14e1af186fb1b4dcd 100644
--- a/product/ERP5/tests/testBug.py
+++ b/product/ERP5/tests/testBug.py
@@ -126,6 +126,7 @@ class TestBug(ERP5TypeTestCase):
                                      start_date='1980-01-01',
                                      stop_date='2099-12-31')
       assignment.open()
+      person.newContent(portal_type='ERP5 Login', reference='dummy').validate()
       self.tic()
       portal_type_list = []
       for portal_type in (self.project_portal_type,
diff --git a/product/ERP5/tests/testCertificateAuthorityTool.py b/product/ERP5/tests/testCertificateAuthorityTool.py
index 94d643900418b8d07e4371b81a31f7e6d599a4ce..139548a1e3059794eed003cfb5ade258105bd0fd 100644
--- a/product/ERP5/tests/testCertificateAuthorityTool.py
+++ b/product/ERP5/tests/testCertificateAuthorityTool.py
@@ -50,6 +50,7 @@ class TestCertificateAuthority(ERP5TypeTestCase):
     person = self.portal.person_module.newContent(portal_type='Person',
       reference=login, password=login)
     person.newContent(portal_type='Assignment').open()
+    person.newContent(portal_type='ERP5 Login', reference=login).validate()
     self.tic()
     return login
 
diff --git a/product/ERP5/tests/testERP5Base.py b/product/ERP5/tests/testERP5Base.py
index 1a66528b91d639c9560bb3bf3b9a7891ded738e0..48fe0ff5424518193c6c62b9355b76f0c5c907d0 100644
--- a/product/ERP5/tests/testERP5Base.py
+++ b/product/ERP5/tests/testERP5Base.py
@@ -1167,14 +1167,14 @@ class TestERP5Base(ERP5TypeTestCase):
     self.tic()
 
     # a user is created
-    user = self.portal.acl_users.getUserById('user_login')
+    user = self.portal.acl_users.getUser('user_login')
     self.assertNotEquals(None, user)
 
     # and this user has a preference created
     newSecurityManager(None, user.__of__(self.portal.acl_users))
     self.assertNotEquals(None,
         self.portal.portal_catalog.getResultValue(portal_type='Preference',
-                                                  owner='user_login'))
+                                                  owner=user.getId()))
     # for his assignent group
     self.assertEqual('group/nexedi',
         self.portal.portal_preferences.getPreferredSectionCategory())
diff --git a/product/ERP5/tests/testERP5Commerce.py b/product/ERP5/tests/testERP5Commerce.py
index 3d29604c3ff082f523e056fe6001ee11494f963a..fe02d40f7b07afffe5800a20790bec4c70baada6 100644
--- a/product/ERP5/tests/testERP5Commerce.py
+++ b/product/ERP5/tests/testERP5Commerce.py
@@ -227,6 +227,7 @@ class TestCommerce(ERP5TypeTestCase):
                     start_date='1972-01-01', stop_date='2999-12-31',
                     group=group, destination_project=destination_project)
     assignment.open()
+    person.newContent(portal_type='ERP5 Login', reference=reference).validate()
     self.tic()
 
     #XXX: Security hack (lucas)
diff --git a/product/ERP5/tests/testERP5Credential.py b/product/ERP5/tests/testERP5Credential.py
index 9b03a11d591b5cc80aaf59151e8daaaffd62767a..690affe5bdbf463483808a111893ccde8c90a837 100644
--- a/product/ERP5/tests/testERP5Credential.py
+++ b/product/ERP5/tests/testERP5Credential.py
@@ -303,8 +303,7 @@ class TestERP5Credential(ERP5TypeTestCase):
     self.portal.ERP5Site_activeLogin(mail_message.getReference())
     self.login()
     self.tic()
-    person = portal_catalog.getResultValue(reference=reference,
-                                           portal_type="Person")
+    person = self.portal.acl_users.getUser(reference).getUserValue()
     assignment_list = person.objectValues(portal_type="Assignment")
     self.assertEqual(len(assignment_list), 1)
     assignment = assignment_list[0]
@@ -380,7 +379,7 @@ class TestERP5Credential(ERP5TypeTestCase):
         last_name='Simpson', reference='homie')
     self.assertEqual(len(result), 1)
     sequence.edit(subscription_request=result[0],
-        person_reference=credential_reference)
+        login_reference=credential_reference)
 
   def stepAcceptSubscriptionRequest(self, sequence=None, sequence_list=None,
       **kw):
@@ -407,9 +406,9 @@ class TestERP5Credential(ERP5TypeTestCase):
 
     # check homie can log in the system
     self._assertUserExists('homie', 'secret')
-    self.login('homie')
+    self.loginByUserName('homie')
     from AccessControl import getSecurityManager
-    self.assertEqual(getSecurityManager().getUser().getIdOrUserName(), 'homie')
+    self.assertEqual(getSecurityManager().getUser().getUserName(), 'homie')
 
   def stepCreateCredentialUpdate(self, sequence=None, sequence_list=None, **kw):
     '''
@@ -418,10 +417,9 @@ class TestERP5Credential(ERP5TypeTestCase):
     '''
     self.login()
     # get the 'homie' person object
-    person_module = self.portal.getDefaultModule('Person')
-    result = person_module.searchFolder(reference='homie')
+    result = self.portal.portal_catalog(portal_type='ERP5 Login', reference='homie')
     self.assertEqual(len(result), 1)
-    homie = result[0]
+    homie = result[0].getParentValue()
 
     # create a credential update
     credential_update_module = self.portal.getDefaultModule(\
@@ -453,9 +451,9 @@ class TestERP5Credential(ERP5TypeTestCase):
 
     # check that informations on the person object have been updated
     person_module = self.portal.getDefaultModule('Person')
-    related_person_result = person_module.searchFolder(reference='homie')
-    self.assertEqual(len(related_person_result), 1)
-    related_person = related_person_result[0]
+    related_login_result = self.portal.portal_catalog(portal_type='ERP5 Login', reference='homie')
+    self.assertEqual(len(related_login_result), 1)
+    related_person = related_login_result[0].getParentValue()
     self.assertEqual(related_person.getLastName(), 'Simpsons')
     self.assertEqual(related_person.getDefaultEmailText(),
     'homie.simpsons@fox.com')
@@ -609,7 +607,7 @@ class TestERP5Credential(ERP5TypeTestCase):
     sequence.edit(barney=person)
     # check barney can log in the system
     self._assertUserExists('barney-login', 'secret')
-    self.login('barney')
+    self.loginByUserName('barney-login')
     from AccessControl import getSecurityManager
     self.assertEqual(getSecurityManager().getUser().getIdOrUserName(), person.Person_getUserId())
 
@@ -658,10 +656,10 @@ class TestERP5Credential(ERP5TypeTestCase):
     self.portal.ERP5Site_newCredentialRecovery(
                     default_email_text=default_email_text)
 
-  def stepLoginAsCurrentPersonReference(self, sequence=None,
+  def stepLoginAsCurrentLoginReference(self, sequence=None,
       sequence_list=None, **kw):
-    person_reference = sequence["person_reference"]
-    self.login(person_reference)
+    login_reference = sequence["login_reference"]
+    self.loginByUserName(login_reference)
 
   def stepCreateCredentialUpdateWithERP5Site_newCredentialUpdate(self,
       sequence=None, sequence_list=None, **kw):
@@ -863,8 +861,7 @@ class TestERP5Credential(ERP5TypeTestCase):
   def stepCheckPersonAfterSubscriptionRequest(self, sequence=None,
       sequence_list=None, **kw):
     self.login()
-    person = self.portal.portal_catalog.getResultValue(
-      reference=sequence["person_reference"], portal_type="Person")
+    person = self.portal.acl_users.getUser(sequence['login_reference']).getUserValue()
     self.assertEqual("Homer", person.getFirstName())
     self.assertEqual("Simpson", person.getLastName())
     self.assertEqual("homer.simpson@fox.com", person.getDefaultEmailText())
@@ -873,16 +870,14 @@ class TestERP5Credential(ERP5TypeTestCase):
 
   def stepSetAuditorRoleToCurrentPerson(self, sequence=None,
       sequence_list=None, **kw):
-    person_reference = sequence["person_reference"]
     self.login()
-    person = self.portal.acl_users.getUser(person_reference).getUserValue()
+    person = self.portal.acl_users.getUser(sequence['login_reference']).getUserValue()
     person.manage_setLocalRoles(person.Person_getUserId(), ["Auditor"])
     self.logout()
 
   def stepCheckPersonAfterUpdatePerson(self, sequence=None,
       sequence_list=None, **kw):
-    person = self.portal.portal_catalog.getResultValue(
-      reference=sequence["person_reference"], portal_type="Person")
+    person = self.portal.acl_users.getUser(sequence['login_reference']).getUserValue()
     self.assertEqual("tom", person.getFirstName())
     self.assertEqual("Simpson", person.getLastName())
     self.assertEqual("tom@host.com", person.getDefaultEmailText())
@@ -1123,8 +1118,7 @@ class TestERP5Credential(ERP5TypeTestCase):
     self.portal.ERP5Site_activeLogin(mail_message.getReference())
     self.login()
     self.tic()
-    person = portal_catalog.getResultValue(reference="barney",
-        portal_type="Person")
+    person = self.portal.acl_users.getUser('barney').getUserValue()
     assignment_list = person.objectValues(portal_type="Assignment")
     self.assertNotEquals(assignment_list, [])
     self.assertEqual(len(assignment_list), 1)
@@ -1233,7 +1227,7 @@ class TestERP5Credential(ERP5TypeTestCase):
            "stepCheckPersonAfterSubscriptionRequest " \
            "SetAuditorRoleToCurrentPerson " \
            "SetAssigneeRoleToCurrentPersonInCredentialUpdateModule Tic " \
-           "LoginAsCurrentPersonReference " \
+           "LoginAsCurrentLoginReference " \
            "CreateCredentialUpdateWithERP5Site_newCredentialUpdate Tic " \
            "SelectCredentialUpdate " \
            "AcceptCredentialUpdate Tic "\
@@ -1296,7 +1290,7 @@ class TestERP5Credential(ERP5TypeTestCase):
     '''
     sequence_list = SequenceList()
     sequence_string = "CreatePersonWithQuestionUsingCamelCase Tic " \
-        "LoginAsCurrentPersonReference " \
+        "LoginAsCurrentLoginReference " \
         "CreateCredentialRecoveryWithSensitiveAnswer Tic " \
         "AcceptCredentialRecovery Tic " \
         "CheckEmailIsSent Tic "\
diff --git a/product/ERP5/tests/testPasswordTool.py b/product/ERP5/tests/testPasswordTool.py
index 81f33cff19fb89dc1e55165b341a7fefbc04c6e6..05f54dd115a8f2b018d9a753fa6518b55e7f9bbb 100644
--- a/product/ERP5/tests/testPasswordTool.py
+++ b/product/ERP5/tests/testPasswordTool.py
@@ -67,7 +67,7 @@ class TestPasswordTool(ERP5TypeTestCase):
     from Products.PluggableAuthService.interfaces.plugins import\
                                                       IAuthenticationPlugin
     uf = self.getUserFolder()
-    self.assertNotEquals(uf.getUserById(login, None), None)
+    self.assertNotEquals(uf.getUser(login), None)
     for plugin_name, plugin in uf._getOb('plugins').listPlugins(
                                 IAuthenticationPlugin ):
       if plugin.authenticateCredentials(
@@ -98,10 +98,15 @@ class TestPasswordTool(ERP5TypeTestCase):
     """
     person = self.portal.person_module.newContent(portal_type="Person",
                                     reference="userA",
-                                    password="passwordA",
                                     default_email_text="userA@example.invalid")
     assignment = person.newContent(portal_type='Assignment')
     assignment.open()
+    login = person.newContent(
+      portal_type='ERP5 Login',
+      reference='userA-login',
+      password='passwordA',
+    )
+    login.validate()
 
   def stepCheckPasswordToolExists(self, sequence=None, sequence_list=None, **kw):
     """
@@ -113,13 +118,13 @@ class TestPasswordTool(ERP5TypeTestCase):
     """
     Check existence of password tool
     """
-    self._assertUserExists('userA', 'passwordA')
+    self._assertUserExists('userA-login', 'passwordA')
 
   def stepCheckUserLoginWithNewPassword(self, sequence=None, sequence_list=None, **kw):
     """
     Check existence of password tool
     """
-    self._assertUserExists('userA', 'secret')
+    self._assertUserExists('userA-login', 'secret')
 
   def stepCheckUserNotLoginWithBadPassword(self, sequence=None, sequence_list=None, **kw):
     """
@@ -137,13 +142,13 @@ class TestPasswordTool(ERP5TypeTestCase):
     """
     Required a new password
     """
-    self.portal.portal_password.mailPasswordResetRequest(user_login="userA")
+    self.portal.portal_password.mailPasswordResetRequest(user_login="userA-login")
 
   def stepTryLostPasswordWithBadUser(self, sequence=None, sequence_list=None, **kw):
     """
     Required a new password
     """
-    self.portal.portal_password.mailPasswordResetRequest(user_login="userZ")
+    self.portal.portal_password.mailPasswordResetRequest(user_login="userZ-login")
 
   def stepCheckNoMailSent(self, sequence=None, sequence_list=None, **kw):
     """
@@ -169,7 +174,7 @@ class TestPasswordTool(ERP5TypeTestCase):
     But random is also check by changeUserPassword, so it's the same
     """
     key = self.portal.portal_password._password_request_dict.keys()[0]
-    self.portal.portal_password.changeUserPassword(user_login="userA",
+    self.portal.portal_password.changeUserPassword(user_login="userA-login",
                                                    password="secret",
                                                    password_confirmation="secret",
                                                    password_key=key)
@@ -183,7 +188,7 @@ class TestPasswordTool(ERP5TypeTestCase):
     """
     key = self.portal.portal_password._password_request_dict.keys()[0]
     sequence.edit(key=key)
-    self.portal.portal_password.changeUserPassword(user_login="userZ",
+    self.portal.portal_password.changeUserPassword(user_login="userZ-login",
                                                    password="secret",
                                                    password_confirmation="secret",
                                                    password_key=key)
@@ -195,7 +200,7 @@ class TestPasswordTool(ERP5TypeTestCase):
     As we already change password, this must npot work anylonger
     """
     key = sequence.get('key')
-    self.portal.portal_password.changeUserPassword(user_login="userA",
+    self.portal.portal_password.changeUserPassword(user_login="userA-login",
                                                    password="passwordA",
                                                    password_confirmation="passwordA",
                                                    password_key=key)
@@ -206,7 +211,7 @@ class TestPasswordTool(ERP5TypeTestCase):
     """
     Try to reset a password with bad random part
     """
-    self.portal.portal_password.changeUserPassword(user_login="userA",
+    self.portal.portal_password.changeUserPassword(user_login="userA-login",
                                                    password="secret",
                                                    password_confirmation="secret",
                                                    password_key="toto")
@@ -302,108 +307,128 @@ class TestPasswordTool(ERP5TypeTestCase):
   def test_two_concurrent_password_reset(self):
     personA = self.portal.person_module.newContent(portal_type="Person",
                                     reference="userA",
-                                    password="passwordA",
                                     default_email_text="userA@example.invalid")
     assignment = personA.newContent(portal_type='Assignment')
     assignment.open()
+    login = personA.newContent(
+      portal_type='ERP5 Login',
+      reference='userA-login',
+      password='passwordA',
+    )
+    login.validate()
 
     personB = self.portal.person_module.newContent(portal_type="Person",
                                     reference="userB",
-                                    password="passwordB",
                                     default_email_text="userB@example.invalid")
     assignment = personB.newContent(portal_type='Assignment')
     assignment.open()
+    login = personB.newContent(
+      portal_type='ERP5 Login',
+      reference='userB-login',
+      password='passwordB',
+    )
+    login.validate()
     self.tic()
 
-    self._assertUserExists('userA', 'passwordA')
-    self._assertUserExists('userB', 'passwordB')
+    self._assertUserExists('userA-login', 'passwordA')
+    self._assertUserExists('userB-login', 'passwordB')
 
     self.assertEqual(0, len(self.portal.portal_password._password_request_dict))
-    self.portal.portal_password.mailPasswordResetRequest(user_login="userA")
+    self.portal.portal_password.mailPasswordResetRequest(user_login="userA-login")
     self.assertEqual(1, len(self.portal.portal_password._password_request_dict))
     key_a = self.portal.portal_password._password_request_dict.keys()[0]
     self.tic()
 
-    self.portal.portal_password.mailPasswordResetRequest(user_login="userB")
+    self.portal.portal_password.mailPasswordResetRequest(user_login="userB-login")
     possible_key_list =\
         self.portal.portal_password._password_request_dict.keys()
     self.assertEqual(2, len(possible_key_list))
     key_b = [k for k in possible_key_list if k != key_a][0]
     self.tic()
 
-    self._assertUserExists('userA', 'passwordA')
-    self._assertUserExists('userB', 'passwordB')
+    self._assertUserExists('userA-login', 'passwordA')
+    self._assertUserExists('userB-login', 'passwordB')
 
-    self.portal.portal_password.changeUserPassword(user_login="userA",
+    self.portal.portal_password.changeUserPassword(user_login="userA-login",
                                                    password="newA",
                                                    password_confirmation="newA",
                                                    password_key=key_a)
     self.tic()
 
-    self._assertUserExists('userA', 'newA')
-    self._assertUserExists('userB', 'passwordB')
+    self._assertUserExists('userA-login', 'newA')
+    self._assertUserExists('userB-login', 'passwordB')
 
-    self.portal.portal_password.changeUserPassword(user_login="userB",
+    self.portal.portal_password.changeUserPassword(user_login="userB-login",
                                                    password="newB",
                                                    password_confirmation="newB",
                                                    password_key=key_b)
     self.tic()
 
-    self._assertUserExists('userA', 'newA')
-    self._assertUserExists('userB', 'newB')
+    self._assertUserExists('userA-login', 'newA')
+    self._assertUserExists('userB-login', 'newB')
 
   def test_login_with_trailing_space(self):
     person = self.portal.person_module.newContent(portal_type="Person",
                                     reference="userZ ",
-                                    password="passwordZ",
                                     default_email_text="userA@example.invalid")
     assignment = person.newContent(portal_type='Assignment')
     assignment.open()
+    login = person.newContent(
+      portal_type='ERP5 Login',
+      reference='userZ-login ',
+      password='passwordZ',
+    )
+    login.validate()
 
     self.tic()
 
-    self._assertUserExists('userZ ', 'passwordZ')
+    self._assertUserExists('userZ-login ', 'passwordZ')
 
     self.assertEqual(0, len(self.portal.portal_password._password_request_dict))
     # No reset should be send if trailing space is not entered
-    self.portal.portal_password.mailPasswordResetRequest(user_login="userZ")
+    self.portal.portal_password.mailPasswordResetRequest(user_login="userZ-login")
     self.assertEqual(0, len(self.portal.portal_password._password_request_dict))
-    self.portal.portal_password.mailPasswordResetRequest(user_login="userZ ")
+    self.portal.portal_password.mailPasswordResetRequest(user_login="userZ-login ")
     self.assertEqual(1, len(self.portal.portal_password._password_request_dict))
 
     key_a = self.portal.portal_password._password_request_dict.keys()[0]
     self.tic()
 
-    self._assertUserExists('userZ ', 'passwordZ')
+    self._assertUserExists('userZ-login ', 'passwordZ')
 
     # Check that password is not changed if trailing space is not entered
-    self.portal.portal_password.changeUserPassword(user_login="userZ",
+    self.portal.portal_password.changeUserPassword(user_login="userZ-login",
                                                    password="newZ",
                                                    password_confirmation="newZ",
                                                    password_key=key_a)
     self.tic()
-    self._assertUserExists('userZ ', 'passwordZ')
+    self._assertUserExists('userZ-login ', 'passwordZ')
 
     # Check that password is changed if trailing space is entered
-    self.portal.portal_password.changeUserPassword(user_login="userZ ",
+    self.portal.portal_password.changeUserPassword(user_login="userZ-login ",
                                                    password="newZ2",
                                                    password_confirmation="newZ2",
                                                    password_key=key_a)
     self.tic()
-    self._assertUserExists('userZ ', 'newZ2')
+    self._assertUserExists('userZ-login ', 'newZ2')
 
   def test_no_email_on_person(self):
     person = self.portal.person_module.newContent(portal_type="Person",
-                                    reference="user",
-                                    password="password",)
+                                    reference="user",)
     assignment = person.newContent(portal_type='Assignment')
     assignment.open()
+    login = person.newContent(
+      portal_type='ERP5 Login',
+      reference='user-login',
+      password='password',
+    )
+    login.validate()
 
     self.tic()
     self.logout()
     ret = self.portal.portal_password.mailPasswordResetRequest(
-                  user_login='user', REQUEST=self.portal.REQUEST)
-    self.assertTrue("portal_status_message=User+user+does+not+have+an+email+"\
+                  user_login='user-login', REQUEST=self.portal.REQUEST)
+    self.assertTrue("portal_status_message=User+user-login+does+not+have+an+email+"\
         "address%2C+please+contact+site+administrator+directly" in str(ret))
 
   def test_acquired_email_on_person(self):
@@ -412,17 +437,22 @@ class TestPasswordTool(ERP5TypeTestCase):
                                     default_email_text="organisation@example.com",)
     person = self.portal.person_module.newContent(portal_type="Person",
                                     reference="user",
-                                    password="password",
                                     default_career_subordination_value=organisation)
     assignment = person.newContent(portal_type='Assignment')
     assignment.open()
+    login = person.newContent(
+      portal_type='ERP5 Login',
+      reference='user-login',
+      password='password',
+    )
+    login.validate()
 
     self.tic()
-    self._assertUserExists('user', 'password')
+    self._assertUserExists('user-login', 'password')
     self.logout()
     ret = self.portal.portal_password.mailPasswordResetRequest(
-                  user_login='user', REQUEST=self.portal.REQUEST)
-    self.assertTrue("portal_status_message=User+user+does+not+have+an+email+"\
+                  user_login='user-login', REQUEST=self.portal.REQUEST)
+    self.assertTrue("portal_status_message=User+user-login+does+not+have+an+email+"\
         "address%2C+please+contact+site+administrator+directly" in str(ret))
 
 class TestPasswordToolWithCRM(TestPasswordTool):
diff --git a/product/ERP5/tests/testWorklist.py b/product/ERP5/tests/testWorklist.py
index 28a7bf65fb40948460b73d891c35f11cae566f58..8999ab48976d0b19c1143f2963ad1e06c36b45ce 100644
--- a/product/ERP5/tests/testWorklist.py
+++ b/product/ERP5/tests/testWorklist.py
@@ -117,6 +117,7 @@ class TestWorklist(ERP5TypeTestCase):
         stop_date = '01/01/2900',
       )
       assignment.open()
+      person.newContent(portal_type='ERP5 Login', reference=user_login).validate()
     # Reindexing is required for the security to work
     self.tic()
 
diff --git a/product/ERP5Banking/tests/TestERP5BankingMixin.py b/product/ERP5Banking/tests/TestERP5BankingMixin.py
index 5e8706fc8447aa5d5aa3c6a8bff0f3e577351508..a56eb899c313a99b60b5bdb49492c663eaac301e 100644
--- a/product/ERP5Banking/tests/TestERP5BankingMixin.py
+++ b/product/ERP5Banking/tests/TestERP5BankingMixin.py
@@ -150,6 +150,10 @@ class TestERP5BankingMixin(ERP5TypeTestCase):
       #   by the assignment workflow when NuxUserGroup is used and
       #   by ERP5Security PAS plugins in the context of PAS use.
       assignment.open()
+      person.newContent(
+        portal_type='ERP5 Login',
+        reference=user_login,
+      ).validate()
 
     if self.PAS_installed:
       # reindexing is required for the security to work
diff --git a/product/ERP5Catalog/tests/testERP5CatalogSecurityUidOptimization.py b/product/ERP5Catalog/tests/testERP5CatalogSecurityUidOptimization.py
index 27898e0b9324438a87fb9e59350fed8b6fbfc701..fa459f9e156e797b62c9ad1b283493eb87b0a144 100644
--- a/product/ERP5Catalog/tests/testERP5CatalogSecurityUidOptimization.py
+++ b/product/ERP5Catalog/tests/testERP5CatalogSecurityUidOptimization.py
@@ -128,6 +128,7 @@ CREATE TABLE alternate_roles_and_users (
         reference='user1')
       user1_id = user1.Person_getUserId()
       user1.newContent(portal_type='Assignment', group='g1').open()
+      user1.newContent(portal_type='ERP5 Login', reference='user1').validate()
       user1.updateLocalRolesOnSecurityGroups()
       self.assertEqual(user1.__ac_local_roles__.get(user1_id), ['Auditor'])
       self.assertEqual(user1.__ac_local_roles__.get('GROUP1'), ['Unknown'])
@@ -136,6 +137,7 @@ CREATE TABLE alternate_roles_and_users (
         reference='user2')
       user2_id = user2.Person_getUserId()
       user2.newContent(portal_type='Assignment', group='g1').open()
+      user2.newContent(portal_type='ERP5 Login', reference='user2').validate()
       user2.updateLocalRolesOnSecurityGroups()
       self.assertEqual(user2.__ac_local_roles__.get(user2_id), ['Auditor'])
       self.assertEqual(user2.__ac_local_roles__.get('GROUP1'), ['Unknown'])
diff --git a/product/ERP5Form/tests/testGUIwithSecurity.py b/product/ERP5Form/tests/testGUIwithSecurity.py
index 9a34dbc31ab04b7ae4528ceaf4fedadb4956aa01..91ec75b1ad002ddf6ef3cb9eb6998beccfe409d6 100644
--- a/product/ERP5Form/tests/testGUIwithSecurity.py
+++ b/product/ERP5Form/tests/testGUIwithSecurity.py
@@ -72,6 +72,7 @@ class TestGUISecurity(ERP5TypeTestCase):
     self.assertTrue('Created Successfully' in message)
     if not hasattr(portal.person_module, 'user'):
       user = portal.person_module.newContent(portal_type='Person', id='user', reference='user')
+      user.newContent(portal_type='ERP5 Login', reference='user').validate()
       asg = user.newContent(portal_type='Assignment')
       asg.setStartDate(DateTime() - 100)
       asg.setStopDate(DateTime() + 100)
diff --git a/product/ERP5OOo/tests/testDeferredStyle.py b/product/ERP5OOo/tests/testDeferredStyle.py
index 936d29e34854db788a7f63a9157c2052a8ebb9e4..72521614b017c2d561ed9dfc5d5dcc645b7f8ae2 100644
--- a/product/ERP5OOo/tests/testDeferredStyle.py
+++ b/product/ERP5OOo/tests/testDeferredStyle.py
@@ -64,10 +64,15 @@ class TestDeferredStyle(ERP5TypeTestCase, ZopeTestCase.Functional):
       person = person_module.newContent(id='pers', portal_type='Person',
                                         reference=self.username,
                                         first_name=self.first_name,
-                                        password=self.password,
                                         default_email_text=self.recipient_email_address)
       assignment = person.newContent(portal_type='Assignment')
       assignment.open()
+      login = person.newContent(
+        portal_type='ERP5 Login',
+        reference=self.username,
+        password=self.password,
+      )
+      login.validate()
     self.tic()
 
   def loginAsUser(self, username):
diff --git a/product/ERP5Security/tests/testERP5Security.py b/product/ERP5Security/tests/testERP5Security.py
index 00a8345aa74aef4d16d8a50e0b4cc79b2562cf78..a82475eadae977b364c77b9d2c29fa426c625b5c 100644
--- a/product/ERP5Security/tests/testERP5Security.py
+++ b/product/ERP5Security/tests/testERP5Security.py
@@ -30,21 +30,26 @@
 """Tests ERP5 User Management.
 """
 
+import itertools
 import transaction
 import unittest
 from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
 from Products.ERP5Type.tests.utils import createZODBPythonScript
 from AccessControl.SecurityManagement import newSecurityManager
 from AccessControl.SecurityManagement import getSecurityManager
+from AccessControl import SpecialUsers
 from Products.PluggableAuthService import PluggableAuthService
 from zope.interface.verify import verifyClass
 from DateTime import DateTime
 from Products import ERP5Security
 from Products.DCWorkflow.DCWorkflow import ValidationFailed
 
+AUTO_LOGIN = object()
+
 class TestUserManagement(ERP5TypeTestCase):
   """Tests User Management in ERP5Security.
   """
+  _login_generator = itertools.count().next
 
   def getTitle(self):
     """Title of the test."""
@@ -52,7 +57,7 @@ class TestUserManagement(ERP5TypeTestCase):
 
   def getBusinessTemplateList(self):
     """List of BT to install. """
-    return ('erp5_base',)
+    return ('erp5_base', 'erp5_administration',)
 
   def beforeTearDown(self):
     """Clears person module and invalidate caches when tests are finished."""
@@ -97,8 +102,8 @@ class TestUserManagement(ERP5TypeTestCase):
     user = uf.getUserById(username).__of__(uf)
     newSecurityManager(None, user)
 
-  def _makePerson(self, open_assignment=1, assignment_start_date=None,
-                  assignment_stop_date=None, **kw):
+  def _makePerson(self, login=AUTO_LOGIN, open_assignment=1, assignment_start_date=None,
+                  assignment_stop_date=None, tic=True, password='secret', **kw):
     """Creates a person in person module, and returns the object, after
     indexing is done. """
     person_module = self.getPersonModule()
@@ -109,8 +114,17 @@ class TestUserManagement(ERP5TypeTestCase):
                                        stop_date=assignment_stop_date,)
     if open_assignment:
       assignment.open()
-    self.tic()
-    return new_person
+    if login is not None:
+      if login is AUTO_LOGIN:
+        login = 'login_%s' % self._login_generator()
+      new_person.newContent(
+        portal_type='ERP5 Login',
+        reference=login,
+        password=password,
+      ).validate()
+    if tic:
+      self.tic()
+    return new_person.Person_getUserId(), login, password
 
   def _assertUserExists(self, login, password):
     """Checks that a user with login and password exists and can log in to the
@@ -146,125 +160,184 @@ class TestUserManagement(ERP5TypeTestCase):
 
   def test_PersonWithLoginPasswordAreUsers(self):
     """Tests a person with a login & password is a valid user."""
-    p = self._makePerson(reference='the_user', password='secret',)
-    self._assertUserExists('the_user', 'secret')
+    _, login, password = self._makePerson()
+    self._assertUserExists(login, password)
 
   def test_PersonLoginCaseSensitive(self):
     """Login/password are case sensitive."""
-    p = self._makePerson(reference='the_user', password='secret',)
-    self._assertUserExists('the_user', 'secret')
-    self._assertUserDoesNotExists('the_User', 'secret')
+    login = 'case_test_user'
+    _, _, password = self._makePerson(login=login)
+    self._assertUserExists(login, password)
+    self._assertUserDoesNotExists('case_test_User', password)
 
   def test_PersonLoginIsNotStripped(self):
     """Make sure 'foo ', ' foo' and ' foo ' do not match user 'foo'. """
-    p = self._makePerson(reference='foo', password='secret',)
-    self._assertUserExists('foo', 'secret')
-    self._assertUserDoesNotExists('foo ', 'secret')
-    self._assertUserDoesNotExists(' foo', 'secret')
-    self._assertUserDoesNotExists(' foo ', 'secret')
+    _, login, password = self._makePerson()
+    self._assertUserExists(login, password)
+    self._assertUserDoesNotExists(login + ' ', password)
+    self._assertUserDoesNotExists(' ' + login, password)
+    self._assertUserDoesNotExists(' ' + login + ' ', password)
 
   def test_PersonLoginCannotBeComposed(self):
     """Make sure ZSQLCatalog keywords cannot be used at login time"""
-    p = self._makePerson(reference='foo', password='secret',)
-    self._assertUserExists('foo', 'secret')
-    self._assertUserDoesNotExists('bar', 'secret')
-    self._assertUserDoesNotExists('bar OR foo', 'secret')
+    _, login, password = self._makePerson()
+    self._assertUserExists(login, password)
+    doest_not_exist = 'bar'
+    self._assertUserDoesNotExists(doest_not_exist, password)
+    self._assertUserDoesNotExists(login + ' OR ' + doest_not_exist, password)
+    self._assertUserDoesNotExists(doest_not_exist + ' OR ' + login, password)
 
   def test_PersonLoginQuote(self):
-    p = self._makePerson(reference="'", password='secret',)
-    self._assertUserExists("'", 'secret')
+    login = "'"
+    _, _, password = self._makePerson(login=login)
+    self._assertUserExists(login, password)
+    login = '"'
+    _, _, password = self._makePerson(login=login)
+    self._assertUserExists(login, password)
 
   def test_PersonLogin_OR_Keyword(self):
-    p = self._makePerson(reference='foo OR bar', password='secret',)
-    self._assertUserExists('foo OR bar', 'secret')
-    self._assertUserDoesNotExists('foo', 'secret')
+    base_login = 'foo'
+    login = base_login + ' OR bar'
+    _, _, password = self._makePerson(login=login)
+    self._assertUserExists(login, password)
+    self._assertUserDoesNotExists(base_login, password)
 
   def test_PersonLoginCatalogKeyWord(self):
     # use something that would turn the username in a ZSQLCatalog catalog keyword
-    p = self._makePerson(reference="foo%", password='secret',)
-    self._assertUserExists("foo%", 'secret')
-    self._assertUserDoesNotExists("foo", 'secret')
-    self._assertUserDoesNotExists("foobar", 'secret')
+    base_login ='foo'
+    login = base_login + '%'
+    _, _, password = self._makePerson(login=login)
+    self._assertUserExists(login, password)
+    self._assertUserDoesNotExists(base_login, password)
+    self._assertUserDoesNotExists(base_login + "bar", password)
 
   def test_PersonLoginNGT(self):
-    p = self._makePerson(reference='< foo', password='secret',)
-    self._assertUserExists('< foo', 'secret')
+    login = '< foo'
+    _, _, password = self._makePerson(login=login)
+    self._assertUserExists(login, password)
+    self._assertUserDoesNotExists('fo', password)
 
   def test_PersonLoginNonAscii(self):
     """Login can contain non ascii chars."""
-    p = self._makePerson(reference='j\xc3\xa9', password='secret',)
-    self._assertUserExists('j\xc3\xa9', 'secret')
+    login = 'j\xc3\xa9'
+    _, _, password = self._makePerson(login=login)
+    self._assertUserExists(login, password)
 
   def test_PersonWithLoginWithEmptyPasswordAreNotUsers(self):
     """Tests a person with a login but no password is not a valid user."""
-    self._makePerson(reference='the_user')
-    self._assertUserDoesNotExists('the_user', None)
-    self._makePerson(reference='another_user', password='',)
-    self._assertUserDoesNotExists('another_user', '')
+    password = None
+    _, login, _ = self._makePerson(password=password)
+    self._assertUserDoesNotExists(login, password)
+    password = ''
+    _, login, self._makePerson(password=password)
+    self._assertUserDoesNotExists(login, password)
 
   def test_PersonWithEmptyLoginAreNotUsers(self):
-    """Tests a person with empty login & password is a valid user."""
-    self._makePerson(reference='', password='secret')
-    self._assertUserDoesNotExists('', 'secret')
+    """Tests a person with empty login & password is not a valid user."""
+    _, login, _ = self._makePerson()
+    pas_user, = self.portal.acl_users.searchUsers(login=login, exact_match=True)
+    pas_login, = pas_user['login_list']
+    login_value = self.portal.restrictedTraverse(pas_login['path'])
+    login_value.invalidate()
+    login_value.setReference('')
+    self.commit()
+    self.assertRaises(ValidationFailed, login_value.validate)
+    self.assertRaises(ValidationFailed, self.portal.portal_workflow.doActionFor, login_value, 'validate_action')
 
   def test_PersonWithLoginWithNotAssignmentAreNotUsers(self):
     """Tests a person with a login & password and no assignment open is not a valid user."""
-    self._makePerson(reference='the_user', password='secret', open_assignment=0)
-    self._assertUserDoesNotExists('the_user', 'secret')
+    _, login, password = self._makePerson(open_assignment=0)
+    self._assertUserDoesNotExists(login, password)
 
-  def test_PersonWithSuperUserLoginCannotBeCreated(self):
-    """Tests one cannot create person with the "super user" special login."""
-    self.assertRaises(RuntimeError, self._makePerson, reference=ERP5Security.SUPER_USER)
+  def _testUserNameExistsButCannotLoginAndCannotCreate(self, login):
+    self.assertTrue(self.getUserFolder().searchUsers(login=login, exact_match=True))
+    self._assertUserDoesNotExists(login, '')
+    self.assertRaises(ValidationFailed, self._makePerson, login=login)
 
   def test_PersonWithSuperUserLogin(self):
     """Tests one cannot use the "super user" special login."""
-    self._assertUserDoesNotExists(ERP5Security.SUPER_USER, '')
-
-  def test_searchUsers(self):
-    p1 = self._makePerson(reference='person1')
-    p2 = self._makePerson(reference='person2')
-    self.assertEqual({'person1', 'person2'},
-      {x['userid'] for x in self.portal.acl_users.searchUsers(id='person')})
-
-  def test_searchUsersExactMatch(self):
-    p = self._makePerson(reference='person')
-    p1 = self._makePerson(reference='person1')
-    p2 = self._makePerson(reference='person2')
-    self.assertEqual(['person', ],
-         [x['userid'] for x in
-           self.portal.acl_users.searchUsers(id='person', exact_match=True)])
-
-  def test_MultiplePersonReference(self):
-    """Tests that it's refused to create two Persons with same reference."""
-    self._makePerson(reference='new_person')
-    self.assertRaises(RuntimeError, self._makePerson, reference='new_person')
+    self._testUserNameExistsButCannotLoginAndCannotCreate(ERP5Security.SUPER_USER)
+
+  def test_PersonWithAnonymousLogin(self):
+    """Tests one cannot use the "anonymous user" special login."""
+    self._testUserNameExistsButCannotLoginAndCannotCreate(SpecialUsers.nobody.getUserName())
+
+  def test_PersonWithSystemUserLogin(self):
+    """Tests one cannot use the "system user" special login."""
+    self._testUserNameExistsButCannotLoginAndCannotCreate(SpecialUsers.system.getUserName())
+
+  def test_searchUserId(self):
+    substring = 'person_id'
+    user_id_set = {substring + '1', '1' + substring}
+    for user_id in user_id_set:
+      self._makePerson(reference=user_id)
+    self.assertEqual(
+      user_id_set,
+      {x['userid'] for x in self.portal.acl_users.searchUsers(id=substring, exact_match=False)},
+    )
+
+  def test_searchLogin(self):
+    substring = 'person_login'
+    login_set = {substring + '1', '1' + substring}
+    for login in login_set:
+      self._makePerson(login=login)
+    self.assertEqual(
+      login_set,
+      {x['login'] for x in self.portal.acl_users.searchUsers(login=substring, exact_match=False)},
+    )
+
+  def test_searchUsersIdExactMatch(self):
+    substring = 'person2_id'
+    self._makePerson(reference=substring)
+    self._makePerson(reference=substring + '1')
+    self._makePerson(reference='1' + substring)
+    self.assertEqual(
+      [substring],
+      [x['userid'] for x in self.portal.acl_users.searchUsers(id=substring, exact_match=True)],
+    )
+
+  def test_searchUsersLoginExactMatch(self):
+    substring = 'person2_login'
+    self._makePerson(login=substring)
+    self._makePerson(login=substring + '1')
+    self._makePerson(login='1' + substring)
+    self.assertEqual(
+      [substring],
+      [x['login'] for x in self.portal.acl_users.searchUsers(login=substring, exact_match=True)],
+    )
+
+  def test_MultipleUsers(self):
+    """Tests that it's refused to create two Persons with same user id."""
+    user_id, login, _ = self._makePerson()
+    self.assertRaises(ValidationFailed, self._makePerson, reference=user_id)
+    self.assertRaises(ValidationFailed, self._makePerson, login=login)
 
   def test_MultiplePersonReferenceWithoutCommit(self):
     """
-    Tests that it's refused to create two Persons with same reference.
+    Tests that it's refused to create two Persons with same user id.
     Check if both persons are created in the same transaction
     """
     person_module = self.getPersonModule()
     new_person = person_module.newContent(
                      portal_type='Person', reference='new_person')
-    self.assertRaises(RuntimeError, person_module.newContent,
+    self.assertRaises(ValidationFailed, person_module.newContent,
                      portal_type='Person', reference='new_person')
 
   def test_MultiplePersonReferenceWithoutTic(self):
     """
-    Tests that it's refused to create two Persons with same reference.
+    Tests that it's refused to create two Persons with same user id.
     Check if both persons are created in 2 different transactions.
     """
     person_module = self.getPersonModule()
     new_person = person_module.newContent(
                      portal_type='Person', reference='new_person')
     self.commit()
-    self.assertRaises(RuntimeError, person_module.newContent,
+    self.assertRaises(ValidationFailed, person_module.newContent,
                      portal_type='Person', reference='new_person')
 
   def test_MultiplePersonReferenceConcurrentTransaction(self):
     """
-    Tests that it's refused to create two Persons with same reference.
+    Tests that it's refused to create two Persons with same user id.
     Check if both persons are created in 2 concurrent transactions.
     For now, just verify that serialize is called on person_module.
     """
@@ -292,67 +365,82 @@ class TestUserManagement(ERP5TypeTestCase):
 
   def test_PersonCopyAndPaste(self):
     """If we copy and paste a person, login must not be copyied."""
-    person = self._makePerson(reference='new_person')
-    person_module = self.getPersonModule()
-    copy_data = person_module.manage_copyObjects([person.getId()])
-    changed, = person_module.manage_pasteObjects(copy_data)
-    self.assertNotEquals(person_module[changed['new_id']].getReference(),
-                         person_module[changed['id']].getReference())
+    user_id, _, _ = self._makePerson(reference='new_person')
+    user, = self.portal.acl_users.searchUsers(id=user_id, exact_match=True)
+    user_value = self.portal.restrictedTraverse(user['path'])
+    container = user_value.getParentValue()
+    changed, = container.manage_pasteObjects(
+      container.manage_copyObjects([user_value.getId()]),
+    )
+    self.assertNotEquals(
+      container[changed['new_id']].Person_getUserId(),
+      user_id,
+    )
 
   def test_PreferenceTool_setNewPassword(self):
     # Preference Tool has an action to change password
-    pers = self._makePerson(reference='the_user', password='secret',)
-    self.tic()
-    self._assertUserExists('the_user', 'secret')
-    self.loginAsUser('the_user')
-    login = [x for x in pers.objectValues(portal_type='ERP5 Login')][0]
+    user_id, login, password = self._makePerson()
+    self._assertUserExists(login, password)
+    pas_user, = self.portal.acl_users.searchUsers(id=user_id, exact_match=True)
+    pas_login, = pas_user['login_list']
+    login_value = self.portal.restrictedTraverse(pas_login['path'])
+    new_password = 'new' + password
+
+    self.loginAsUser(user_id)
     result = self.portal.portal_preferences.PreferenceTool_setNewPassword(
       dialog_id='PreferenceTool_viewChangePasswordDialog',
-      current_password='wrong_secret',
-      new_password='new_secret',
+      current_password='bad' + password,
+      new_password=new_password,
     )
     self.assertEqual(result, self.portal.absolute_url()+'/portal_preferences/PreferenceTool_viewChangePasswordDialog?portal_status_message=Current%20password%20is%20wrong.')
+
+    self.login()
+    self._assertUserExists(login, password)
+    self._assertUserDoesNotExists(login, new_password)
+
+    self.loginAsUser(user_id)
     result = self.portal.portal_preferences.PreferenceTool_setNewPassword(
       dialog_id='PreferenceTool_viewChangePasswordDialog',
-      current_password='secret',
-      new_password='new_secret',
+      current_password=password,
+      new_password=new_password,
     )
     self.assertEqual(result, self.portal.absolute_url()+'/logout')
-    self._assertUserExists('the_user', 'new_secret')
-    self._assertUserDoesNotExists('the_user', 'secret')
 
+    self.login()
+    self._assertUserExists(login, new_password)
+    self._assertUserDoesNotExists(login, password)
     # password is not stored in plain text
-    self.assertNotEquals('new_secret', pers.getPassword())
-
+    self.assertNotEquals(new_password, self.portal.restrictedTraverse(pas_user['path']).getPassword())
 
   def test_OpenningAssignmentClearCache(self):
     """Openning an assignment for a person clear the cache automatically."""
-    pers = self._makePerson(reference='the_user', password='secret',
-                            open_assignment=0)
-    self._assertUserDoesNotExists('the_user', 'secret')
+    user_id, login, password = self._makePerson(open_assignment=0)
+    self._assertUserDoesNotExists(login, password)
+    user, = self.portal.acl_users.searchUsers(id=user_id, exact_match=True)
+    pers = self.portal.restrictedTraverse(user['path'])
     assi = pers.newContent(portal_type='Assignment')
     assi.open()
     self.commit()
-    self._assertUserExists('the_user', 'secret')
+    self._assertUserExists(login, password)
     assi.close()
     self.commit()
-    self._assertUserDoesNotExists('the_user', 'secret')
+    self._assertUserDoesNotExists(login, password)
 
   def test_PersonNotIndexedNotCached(self):
-    pers = self._makePerson(password='secret',)
-    pers.setReference('the_user')
+    user_id, login, password = self._makePerson(tic=False)
     # not indexed yet
-    self._assertUserDoesNotExists('the_user', 'secret')
-
+    self._assertUserDoesNotExists(login, password)
     self.tic()
-
-    self._assertUserExists('the_user', 'secret')
+    self._assertUserExists(login, password)
 
   def test_PersonNotValidNotCached(self):
-    pers = self._makePerson(reference='the_user', password='other',)
-    self._assertUserDoesNotExists('the_user', 'secret')
-    pers.setPassword('secret')
-    self._assertUserExists('the_user', 'secret')
+    user_id, login, password = self._makePerson()
+    password += '2'
+    pas_user, = self.portal.acl_users.searchUsers(login=login, exact_match=True)
+    pas_login, = pas_user['login_list']
+    self._assertUserDoesNotExists(login, password)
+    self.portal.restrictedTraverse(pas_login['path']).setPassword(password)
+    self._assertUserExists(login, password)
 
   def test_PersonLoginMigration(self):
     self.portal.acl_users.manage_addProduct['ERP5Security'].addERP5UserManager('erp5_users')
@@ -363,6 +451,7 @@ class TestUserManagement(ERP5TypeTestCase):
     pers = self.portal.person_module.newContent(
       portal_type='Person',
       reference='the_user',
+      reference=None,
     )
     pers.newContent(
       portal_type='Assignment',
@@ -376,6 +465,7 @@ class TestUserManagement(ERP5TypeTestCase):
     self.tic()
     self._assertUserExists('the_user', 'secret')
     self.assertEqual(pers.getPassword(), None)
+    self.assertEqual(pers.Person_getUserId(), 'the_user')
     login = pers.objectValues(portal_type='ERP5 Login')[0]
     login.setPassword('secret2')
     self.portal.portal_caches.clearAllCache()
@@ -397,85 +487,99 @@ class TestUserManagement(ERP5TypeTestCase):
   def test_AssignmentWithDate(self):
     """Tests a person with an assignment with correct date is a valid user."""
     date = DateTime()
-    p = self._makePerson(reference='the_user', password='secret',
-                         assignment_start_date=date-5,
-                         assignment_stop_date=date+5)
-    self._assertUserExists('the_user', 'secret')
+    _, login, password = self._makePerson(
+      assignment_start_date=date - 5,
+      assignment_stop_date=date + 5,
+    )
+    self._assertUserExists(login, password)
 
   def test_AssignmentWithBadStartDate(self):
     """Tests a person with an assignment with bad start date is not a valid user."""
     date = DateTime()
-    p = self._makePerson(reference='the_user', password='secret',
-                         assignment_start_date=date+1,
-                         assignment_stop_date=date+5)
-    self._assertUserDoesNotExists('the_user', 'secret')
+    _, login, password = self._makePerson(
+      assignment_start_date=date + 1,
+      assignment_stop_date=date + 5,
+    )
+    self._assertUserDoesNotExists(login, password)
 
   def test_AssignmentWithBadStopDate(self):
     """Tests a person with an assignment with bad stop date is not a valid user."""
     date = DateTime()
-    p = self._makePerson(reference='the_user', password='secret',
-                         assignment_start_date=date-5,
-                         assignment_stop_date=date-1)
-    self._assertUserDoesNotExists('the_user', 'secret')
+    _, login, password = self._makePerson(
+      assignment_start_date=date - 5,
+      assignment_stop_date=date - 1,
+    )
+    self._assertUserDoesNotExists(login, password)
 
   def test_DeletedPersonIsNotUser(self):
-    p = self._makePerson(reference='the_user', password='secret')
-    self._assertUserExists('the_user', 'secret')
-
-    p.delete()
+    user_id, login, password = self._makePerson()
+    self._assertUserExists(login, password)
+    acl_user, = self.portal.acl_users.searchUsers(id=user_id, exact_match=True)
+    self.portal.restrictedTraverse(acl_user['path']).delete()
     self.commit()
-
-    self._assertUserDoesNotExists('the_user', 'secret')
+    self._assertUserDoesNotExists(login, password)
 
   def test_ReallyDeletedPersonIsNotUser(self):
-    p = self._makePerson(reference='the_user', password='secret')
-    self._assertUserExists('the_user', 'secret')
-
+    user_id, login, password = self._makePerson()
+    acl_user, = self.portal.acl_users.searchUsers(id=user_id, exact_match=True)
+    p = self.portal.restrictedTraverse(acl_user['path'])
+    self._assertUserExists(login, password)
     p.getParentValue().deleteContent(p.getId())
     self.commit()
-
-    self._assertUserDoesNotExists('the_user', 'secret')
+    self._assertUserDoesNotExists(login, password)
 
   def test_InvalidatedPersonIsUser(self):
-    p = self._makePerson(reference='the_user', password='secret')
-    self._assertUserExists('the_user', 'secret')
-
+    user_id, login, password = self._makePerson()
+    acl_user, = self.portal.acl_users.searchUsers(id=user_id, exact_match=True)
+    p = self.portal.restrictedTraverse(acl_user['path'])
+    self._assertUserExists(login, password)
     p.validate()
     p.invalidate()
     self.commit()
+    self._assertUserExists(login, password)
 
-    self._assertUserExists('the_user', 'secret')
-
-  def test_PersonLoginIsPossibleToUnset(self):
-    """Make sure that it is possible to remove reference"""
-    person = self._makePerson(reference='foo', password='secret',)
+  def test_UserIdIsPossibleToUnset(self):
+    """Make sure that it is possible to remove user id"""
+    user_id, login, password = self._makePerson()
+    acl_user, = self.portal.acl_users.searchUsers(id=user_id, exact_match=True)
+    person = self.portal.restrictedTraverse(acl_user['path'])
     person.setReference(None)
     self.tic()
-    self.assertEqual(None, person.getReference())
+    self.assertEqual(None, person.Person_getUserId())
 
-  def test_duplicatePersonReference(self):
-    person1 = self._makePerson(reference='foo', password='secret',)
-    self.tic()
-    self.assertRaises(RuntimeError, self._makePerson,
-                      reference='foo', password='secret',)
+  def test_duplicatePersonUserId(self):
+    user_id, _, _ = self._makePerson()
+    self.assertRaises(ValidationFailed, self._makePerson, reference=user_id)
 
   def test_duplicateLoginReference(self):
-    person1 = self._makePerson(reference='foo', password='secret',)
-    self.tic()
-    person2 = self._makePerson(reference='bar', password='secret',)
-    login = person2.objectValues(portal_type='ERP5 Login')[0]
-    login.invalidate()
-    login.setReference('foo')
-    self.assertRaises(ValidationFailed, self.portal.portal_workflow.doActionFor, login, 'validate_action')
-
-  def test_duplicateLoginReferenceInSameTransaction(self):
-    person1 = self._makePerson(reference='foo', password='secret', tic=False)
-    person2 = self._makePerson(reference='bar', password='secret', tic=False)
-    login = person2.newContent(portal_type='ERP5 Login')
-    login = person2.objectValues(portal_type='ERP5 Login')[0]
-    login.invalidate()
-    login.setReference('foo')
-    self.portal.portal_workflow.doActionFor(login, 'validate_action')
+    _, login1, _ = self._makePerson()
+    _, login2, _ = self._makePerson()
+    pas_user2, = self.portal.acl_users.searchUsers(login=login2, exact_match=True)
+    pas_login2, = pas_user2['login_list']
+    login2_value = self.portal.restrictedTraverse(pas_login2['path'])
+    login2_value.invalidate()
+    login2_value.setReference(login1)
+    self.commit()
+    self.assertRaises(ValidationFailed, login2_value.validate)
+    self.assertRaises(ValidationFailed, self.portal.portal_workflow.doActionFor, login2_value, 'validate_action')
+
+  def _duplicateLoginReference(self, commit):
+    _, login1, _ = self._makePerson(tic=False)
+    user_id2, login2, _ = self._makePerson(tic=False)
+    if commit:
+      self.commit()
+    # Note: cannot rely on catalog, on purpose.
+    person_value, = [
+      x for x in self.portal.person_module.objectValues()
+      if x.Person_getUserId() == user_id2
+    ]
+    login_value, = [
+      x for x in person_value.objectValues(portal_type='ERP5 Login')
+      if x.getReference() == login2
+    ]
+    login_value.invalidate()
+    login_value.setReference(login1)
+    self.portal.portal_workflow.doActionFor(login_value, 'validate_action')
     result = self.portal.portal_alarms.check_duplicate_login_reference.ERP5Site_checkDuplicateLoginReferenceLogin()
     self.assertEqual(result, None)
     self.tic()
@@ -483,19 +587,11 @@ class TestUserManagement(ERP5TypeTestCase):
     self.assertEqual(len(result.getResultList()), 1)
     self.assertEqual(result.getResultList()[0].summary, 'Logins having the same reference exist')
 
+  def test_duplicateLoginReferenceInSameTransaction(self):
+    self._duplicateLoginReference(False)
+
   def test_duplicateLoginReferenceInAnotherTransaction(self):
-    person1 = self._makePerson(reference='foo', password='secret', tic=False)
-    person2 = self._makePerson(reference='bar', password='secret', tic=False)
-    self.commit()
-    login = person2.newContent(portal_type='ERP5 Login')
-    login.setReference('foo')
-    self.portal.portal_workflow.doActionFor(login, 'validate_action')
-    result = self.portal.portal_alarms.check_duplicate_login_reference.ERP5Site_checkDuplicateLoginReferenceLogin()
-    self.assertEqual(result, None)
-    self.tic()
-    result = self.portal.portal_alarms.check_duplicate_login_reference.ERP5Site_checkDuplicateLoginReferenceLogin()
-    self.assertEqual(len(result.getResultList()), 1)
-    self.assertEqual(result.getResultList()[0].summary, 'Logins having the same reference exist')
+    self._duplicateLoginReference(True)
 
 class TestUserManagementExternalAuthentication(TestUserManagement):
   def getTitle(self):
@@ -522,13 +618,9 @@ class TestUserManagementExternalAuthentication(TestUserManagement):
      Make sure that we can grant security using a ERP5 External Authentication Plugin.
     """
 
-    reference = 'external_auth_person'
-    loginable_person = self.getPersonModule().newContent(portal_type='Person',
-                                                         reference=reference,
-                                                         password='guest')
-    assignment = loginable_person.newContent(portal_type='Assignment')
-    assignment.open()
-    self.tic()
+    _, login, _ = self._makePerson()
+    pas_user, = self.portal.acl_users.searchUsers(login=login, exact_match=True)
+    reference = self.portal.restrictedTraverse(pas_user['path']).getReference()
 
     base_url = self.portal.absolute_url(relative=1)
 
@@ -542,7 +634,7 @@ class TestUserManagementExternalAuthentication(TestUserManagement):
     # self.assertTrue(response.headers['location'].endswith('login_form'))
 
     # view front page we should be logged in if we use authentication key
-    response = self.publish(base_url, env={self.user_id_key.replace('-', '_').upper():reference})
+    response = self.publish(base_url, env={self.user_id_key.replace('-', '_').upper(): login})
     self.assertEqual(response.getStatus(), 200)
     self.assertTrue(reference in response.getBody())
 
@@ -579,12 +671,9 @@ class TestLocalRoleManagement(ERP5TypeTestCase):
       base_cat.newContent(portal_type='Category',
                           id='subcat',
                           codification="%s1" % code)
-    # add another function subcategory.
-    function_category = category_tool['function']
-    if function_category.get('another_subcat', None) is None:
-      function_category.newContent(portal_type='Category',
-                                   id='another_subcat',
-                                   codification='F2')
+      base_cat.newContent(portal_type='Category',
+                          id='another_subcat',
+                          codification="%s2" % code)
     self.defined_category = "group/subcat\n"\
                             "site/subcat\n"\
                             "function/subcat"
@@ -595,13 +684,15 @@ class TestLocalRoleManagement(ERP5TypeTestCase):
     self.username = 'usérn@me'
     # create a user and open an assignement
     pers = self.getPersonModule().newContent(portal_type='Person',
-                                             reference=self.username,
-                                             password=self.username)
+                                             reference=self.username)
     assignment = pers.newContent( portal_type='Assignment',
                                   group='subcat',
                                   site='subcat',
                                   function='subcat' )
     assignment.open()
+    pers.newContent(portal_type='ERP5 Login',
+                    reference=self.username,
+                    password=self.username).validate()
     self.person = pers
     self.tic()
 
@@ -638,7 +729,7 @@ class TestLocalRoleManagement(ERP5TypeTestCase):
 
   def getBusinessTemplateList(self):
     """List of BT to install. """
-    return ('erp5_base', 'erp5_web', 'erp5_ingestion', 'erp5_dms',)
+    return ('erp5_base', 'erp5_web', 'erp5_ingestion', 'erp5_dms', 'erp5_administration')
 
   def test_RolesManagerInterfaces(self):
     """Tests group manager plugin respects interfaces."""
@@ -670,6 +761,30 @@ class TestLocalRoleManagement(ERP5TypeTestCase):
     self.assertEqual(['Assignor'], obj.__ac_local_roles__.get('F1_G1_S1'))
     self.assertTrue('Assignor' in user.getRolesInContext(obj))
     self.assertFalse('Assignee' in user.getRolesInContext(obj))
+
+    # check if assignment change is effective immediately
+    self.login()
+    res = self.publish(self.portal.absolute_url_path() + \
+                       '/Base_viewSecurity?__ac_name=%s&__ac_password=%s' % \
+                       (self.username, self.username))
+    self.assertEqual([x for x in res.body.splitlines() if x.startswith('-->')],
+                     ["--> ['F1_G1_S1']"], res.body)
+    assignment = self.person.newContent( portal_type='Assignment',
+                                  group='subcat',
+                                  site='subcat',
+                                  function='another_subcat' )
+    assignment.open()
+    res = self.publish(self.portal.absolute_url_path() + \
+                       '/Base_viewSecurity?__ac_name=%s&__ac_password=%s' % \
+                       (self.username, self.username))
+    self.assertEqual([x for x in res.body.splitlines() if x.startswith('-->')],
+                     ["--> ['F1_G1_S1']", "--> ['F2_G1_S1']"], res.body)
+    assignment.setGroup('another_subcat')
+    res = self.publish(self.portal.absolute_url_path() + \
+                       '/Base_viewSecurity?__ac_name=%s&__ac_password=%s' % \
+                       (self.username, self.username))
+    self.assertEqual([x for x in res.body.splitlines() if x.startswith('-->')],
+                     ["--> ['F1_G1_S1']", "--> ['F2_G2_S1']"], res.body)
     self.abort()
 
   def testLocalRolesGroupId(self):
@@ -722,7 +837,7 @@ class TestLocalRoleManagement(ERP5TypeTestCase):
     """Test dynamic role generation when an assignment defines several functions
     """
     assignment, = self.portal.portal_catalog(portal_type='Assignment',
-                                             parent_reference=self.username)
+                                             parent_reference=self.person.getReference())
     assignment.setFunctionList(('subcat', 'another_subcat'))
     self._getTypeInfo().newContent(portal_type='Role Information',
       role_name='Assignee',
@@ -782,6 +897,9 @@ class TestLocalRoleManagement(ERP5TypeTestCase):
     assignment = loginable_person.newContent(portal_type='Assignment',
                                              function='another_subcat')
     assignment.open()
+    loginable_person.newContent(portal_type='ERP5 Login',
+                                reference='guest',
+                                password='guest').validate()
     self.tic()
 
     person_module_type_information = self.getTypesTool()['Person Module']
@@ -836,11 +954,13 @@ class TestLocalRoleManagement(ERP5TypeTestCase):
 
     reference = 'UserReferenceTextWhichShouldBeHardToGeneratedInAnyHumanOrComputerLanguage'
     loginable_person = self.getPersonModule().newContent(portal_type='Person',
-                                                         reference=reference,
-                                                         password='guest')
+                                                         reference=reference)
     assignment = loginable_person.newContent(portal_type='Assignment',
                                              function='another_subcat')
     assignment.open()
+    loginable_person.newContent(portal_type='ERP5 Login',
+                                reference=reference,
+                                password='guest').validate()
     portal_types = portal.portal_types
     for portal_type in ('Person Module', 'Person', 'Web Site Module', 'Web Site',
                         'Web Page'):
diff --git a/product/ERP5Type/tests/ERP5TypeTestCase.py b/product/ERP5Type/tests/ERP5TypeTestCase.py
index 2d288cc62e963a36aaa61db48e8399602bd96524..8627bf7d3f55034b903e2cdf526db14ca5f21156 100644
--- a/product/ERP5Type/tests/ERP5TypeTestCase.py
+++ b/product/ERP5Type/tests/ERP5TypeTestCase.py
@@ -471,8 +471,11 @@ class ERP5TypeTestCaseMixin(ProcessingNodeTestCase, PortalTestCase):
 
       person = self.portal.person_module.newContent(portal_type='Person',
                                                     reference=reference,
-                                                    password=password,
                                                     **person_kw)
+      login = person.newContent(portal_type='ERP5 Login',
+                                reference=reference,
+                                password=password)
+      login.validate()
       return person
 
     def createUserAssignment(self, user, assignment_kw):