diff --git a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getExternalLogin.py b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getUserValue.py
similarity index 100%
rename from bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getExternalLogin.py
rename to bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getUserValue.py
diff --git a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getExternalLogin.xml b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getUserValue.xml
similarity index 96%
rename from bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getExternalLogin.xml
rename to bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getUserValue.xml
index f6aa05a4b62ada596daf446b2a330df239f4bdee..ef6d82513f1f93024080546a26974ce18485ac86 100644
--- a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getExternalLogin.xml
+++ b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/AccessToken_getUserValue.xml
@@ -54,7 +54,7 @@
         </item>
         <item>
             <key> <string>id</string> </key>
-            <value> <string>AccessToken_getExternalLogin</string> </value>
+            <value> <string>AccessToken_getUserValue</string> </value>
         </item>
       </dictionary>
     </pickle>
diff --git a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getExternalLogin.py b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getUserValue.py
similarity index 92%
rename from bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getExternalLogin.py
rename to bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getUserValue.py
index e15560b82e981fc25da6972873cca818e2f2bdc0..1082749445339af562cf8752a5f3dc82d1f7ccd1 100644
--- a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getExternalLogin.py
+++ b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getUserValue.py
@@ -14,7 +14,7 @@ if access_token_document.getValidationState() == 'validated':
 
     agent_document = access_token_document.getAgentValue()
     if agent_document is not None:
-      result = agent_document.Person_getUserId()
+      result = agent_document
       comment = "Token usage accepted"
 
   access_token_document.invalidate(comment=comment)
diff --git a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getExternalLogin.xml b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getUserValue.xml
similarity index 96%
rename from bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getExternalLogin.xml
rename to bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getUserValue.xml
index 75149e9cf552843f4246527890cd0de07f4f4840..e27079e582e40eb4f11b0ae46058833cc3d68a55 100644
--- a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getExternalLogin.xml
+++ b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/OneTimeRestrictedAccessToken_getUserValue.xml
@@ -54,7 +54,7 @@
         </item>
         <item>
             <key> <string>id</string> </key>
-            <value> <string>OneTimeRestrictedAccessToken_getExternalLogin</string> </value>
+            <value> <string>OneTimeRestrictedAccessToken_getUserValue</string> </value>
         </item>
       </dictionary>
     </pickle>
diff --git a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getExternalLogin.py b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getUserValue.py
similarity index 93%
rename from bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getExternalLogin.py
rename to bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getUserValue.py
index 24685e0cc1bfe6e40bb3fe31b05bb2e1e1bd23db..358798ce3f4184d291bf74068709091bbe66f966 100644
--- a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getExternalLogin.py
+++ b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getUserValue.py
@@ -19,9 +19,9 @@ if access_token_document.getValidationState() == 'validated':
     # use hmac.compare_digest and not string comparison to avoid timing attacks
     if not hmac.compare_digest(access_token_document.getReference(), reference):
       return None
-    
+
     agent_document = access_token_document.getAgentValue()
     if agent_document is not None:
-      result = agent_document.Person_getUserId()
+      result = agent_document
 
 return result
diff --git a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getExternalLogin.xml b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getUserValue.xml
similarity index 96%
rename from bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getExternalLogin.xml
rename to bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getUserValue.xml
index a126952abf365ac81694e35dc1e37478a533b081..e8c7c5a41cbaf6d7b858f966e4cf543114c5c6be 100644
--- a/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getExternalLogin.xml
+++ b/bt5/erp5_access_token/SkinTemplateItem/portal_skins/erp5_access_token/RestrictedAccessToken_getUserValue.xml
@@ -54,7 +54,7 @@
         </item>
         <item>
             <key> <string>id</string> </key>
-            <value> <string>RestrictedAccessToken_getExternalLogin</string> </value>
+            <value> <string>RestrictedAccessToken_getUserValue</string> </value>
         </item>
       </dictionary>
     </pickle>
diff --git a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessToken.py b/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessToken.py
new file mode 100644
index 0000000000000000000000000000000000000000..31c1991cd27930a251d8272e31c92fd282081a76
--- /dev/null
+++ b/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessToken.py
@@ -0,0 +1,414 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (c) 2002-2019 Nexedi SA and Contributors. All Rights Reserved.
+#                    Tristan Cavelier <tristan.cavelier@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+from ZPublisher.HTTPRequest import HTTPRequest
+from ZPublisher.HTTPResponse import HTTPResponse
+from DateTime import DateTime
+import base64
+import StringIO
+from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
+from Products.ERP5Security.ERP5DumbHTTPExtractionPlugin import ERP5DumbHTTPExtractionPlugin
+
+
+class AccessTokenTestCase(ERP5TypeTestCase):
+  def getBusinessTemplateList(self):
+    return ('erp5_base',
+            'erp5_access_token')
+
+  def _createPerson(self, new_id, password=None):
+    """Creates a person in person module, and returns the object, after
+    indexing is done. """
+    person_module = self.getPersonModule()
+    person = person_module.newContent(portal_type='Person',
+      reference='TESTP-' + new_id)
+    if password:
+      person.setPassword(password)
+    person.newContent(portal_type = 'Assignment').open()
+    self.tic()
+    return person
+
+
+class TestERP5AccessTokenSkins(AccessTokenTestCase):
+  test_token_extraction_id = 'test_erp5_access_token_extraction'
+
+  def generateNewId(self):
+    return str(self.portal.portal_ids.generateNewId(
+         id_group=('erp5_access_token_test_id')))
+
+  def afterSetUp(self):
+    """
+    This is ran before anything, used to set the environment
+    """
+    self.new_id = self.generateNewId()
+    self._setupAccessTokenExtraction()
+    self.tic()
+
+  def _setupAccessTokenExtraction(self):
+    pas = self.portal.acl_users
+    access_extraction_list = [q for q in pas.objectValues() \
+        if q.meta_type == 'ERP5 Access Token Extraction Plugin']
+    if len(access_extraction_list) == 0:
+      dispacher = pas.manage_addProduct['ERP5Security']
+      dispacher.addERP5AccessTokenExtractionPlugin(self.test_token_extraction_id)
+      getattr(pas, self.test_token_extraction_id).manage_activateInterfaces(
+        ('IExtractionPlugin', 'IAuthenticationPlugin'))
+    elif len(access_extraction_list) == 1:
+      self.test_token_extraction_id = access_extraction_list[0].getId()
+    elif len(access_extraction_list) > 1:
+      raise ValueError
+    self.commit()
+
+  def _getTokenCredential(self, request):
+    """Authenticate the request and return (user_id, login) or None if not authorized."""
+    plugin = getattr(self.portal.acl_users, self.test_token_extraction_id)
+    return plugin.authenticateCredentials(plugin.extractCredentials(request))
+
+  def _createRestrictedAccessToken(self, new_id, person, method, url_string):
+    access_token = self.portal.access_token_module.newContent(
+                    portal_type="Restricted Access Token",
+                    url_string=url_string,
+                    url_method=method,
+                  )
+    if person:
+      access_token.edit(agent_value=person)
+    return access_token
+
+  def _createOneTimeRestrictedAccessToken(self, new_id, person, method, url_string):
+    access_token = self.portal.access_token_module.newContent(
+                    portal_type="One Time Restricted Access Token",
+                    url_string=url_string,
+                    url_method=method,
+                  )
+    if person:
+      access_token.edit(agent_value=person)
+    return access_token
+
+  def test_working_token(self):
+    person = self._createPerson(self.new_id)
+    access_url = "http://exemple.com/foo"
+    access_method = "GET"
+    access_token = self._createRestrictedAccessToken(self.new_id,
+                        person,
+                        access_method,
+                        access_url)
+    access_token.validate()
+    self.tic()
+
+    self.portal.REQUEST.form["access_token"] = access_token.getId()
+    self.portal.REQUEST["REQUEST_METHOD"] = access_method
+    self.portal.REQUEST["ACTUAL_URL"] = access_url
+    self.portal.REQUEST.form["access_token_secret"] = access_token.getReference()
+
+    result = self._getTokenCredential(self.portal.REQUEST)
+    self.assertTrue(result)
+    user_id, login = result
+    self.assertEqual(user_id, person.Person_getUserId())
+    # tokens have a login value, for auditing purposes
+    self.assertEqual(access_token.getRelativeUrl(), login)
+
+  def test_bad_token(self):
+    person = self._createPerson(self.new_id)
+    access_url = "http://exemple.com/foo"
+    access_method = "GET"
+    access_token = self._createRestrictedAccessToken(self.new_id,
+                        person,
+                        access_method,
+                        access_url)
+    access_token.validate()
+    self.tic()
+
+    self.portal.REQUEST.form["access_token"] = "XYSYDT-YDTYSD"
+    self.portal.REQUEST["REQUEST_METHOD"] = access_method
+    self.portal.REQUEST["ACTUAL_URL"] = access_url
+    self.portal.REQUEST.form["access_token_secret"] = access_token.getReference()
+
+    result = self._getTokenCredential(self.portal.REQUEST)
+    self.assertFalse(result)
+
+  def test_RestrictedAccessToken_getUserValue(self):
+    person = self._createPerson(self.new_id)
+    access_url = "http://exemple.com/foo"
+    access_method = "GET"
+    access_token = self._createRestrictedAccessToken(self.new_id,
+                        person,
+                        access_method,
+                        access_url)
+    access_token.validate()
+    self.tic()
+
+    self.portal.REQUEST["REQUEST_METHOD"] = access_method
+    self.portal.REQUEST["ACTUAL_URL"] = access_url
+    self.portal.REQUEST.form["access_token_secret"] = access_token.getReference()
+
+    result = access_token.RestrictedAccessToken_getUserValue()
+
+    self.assertEqual(result, person)
+    self.assertEqual(access_token.getValidationState(), 'validated')
+
+  def test_RestrictedAccessToken_getUserValue_access_token_secret(self):
+    person = self._createPerson(self.new_id)
+    access_url = "http://exemple.com/foo"
+    access_method = "GET"
+    access_token = self._createRestrictedAccessToken(self.new_id,
+                        person,
+                        access_method,
+                        access_url)
+    access_token.validate()
+    self.tic()
+
+    self.portal.REQUEST["REQUEST_METHOD"] = access_method
+    self.portal.REQUEST["ACTUAL_URL"] = access_url
+
+    result = access_token.RestrictedAccessToken_getUserValue()
+    self.assertEqual(result, None)
+
+    self.portal.REQUEST.form["access_token_secret"] = "XYXYXYXY"
+    self.assertEqual(result, None)
+
+    self.portal.REQUEST.form["access_token_secret"] = access_token.getReference()
+
+    result = access_token.RestrictedAccessToken_getUserValue()
+
+    self.assertEqual(result, person)
+    self.assertEqual(access_token.getValidationState(), 'validated')
+
+  def test_RestrictedAccessToken_getUserValue_no_agent(self):
+    access_url = "http://exemple.com/foo"
+    access_method = "GET"
+    access_token = self._createRestrictedAccessToken(self.new_id,
+                        None,
+                        access_method,
+                        access_url)
+    access_token.validate()
+    self.tic()
+
+    self.portal.REQUEST["REQUEST_METHOD"] = access_method
+    self.portal.REQUEST["ACTUAL_URL"] = access_url
+    self.portal.REQUEST.form["access_token_secret"] = access_token.getReference()
+
+    result = access_token.RestrictedAccessToken_getUserValue()
+    self.assertEqual(result, None)
+
+  def test_RestrictedAccessToken_getUserValue_wrong_values(self):
+    person = self._createPerson(self.new_id)
+    access_url = "http://exemple.com/foo"
+    access_method = "GET"
+    access_token = self._createRestrictedAccessToken(self.new_id,
+                        person,
+                        access_method,
+                        access_url)
+    self.tic()
+    result = access_token.RestrictedAccessToken_getUserValue()
+    self.assertEqual(result, None)
+
+    access_token.validate()
+    self.tic()
+
+    self.portal.REQUEST["REQUEST_METHOD"] = "POST"
+    self.portal.REQUEST["ACTUAL_URL"] = access_url
+    self.portal.REQUEST.form["access_token_secret"] = access_token.getReference()
+
+    result = access_token.RestrictedAccessToken_getUserValue()
+    self.assertEqual(result, None)
+
+    self.portal.REQUEST["ACTUAL_URL"] = "http://exemple.com/foo.bar"
+
+    result = access_token.RestrictedAccessToken_getUserValue()
+    self.assertEqual(result, None)
+
+    access_token.invalidate()
+    self.tic()
+
+    result = access_token.RestrictedAccessToken_getUserValue()
+    self.assertEqual(result, None)
+
+
+  def test_OneTimeRestrictedAccessToken_getUserValue(self):
+    person = self._createPerson(self.new_id)
+    access_url = "http://exemple.com/foo"
+    access_method = "GET"
+    access_token = self._createOneTimeRestrictedAccessToken(self.new_id,
+                        person,
+                        access_method,
+                        access_url)
+    access_token.validate()
+    self.tic()
+
+    self.portal.REQUEST["REQUEST_METHOD"] = access_method
+    self.portal.REQUEST["ACTUAL_URL"] = access_url
+
+    result = access_token.OneTimeRestrictedAccessToken_getUserValue()
+
+    self.assertEqual(result, person)
+    self.assertEqual(access_token.getValidationState(), 'invalidated')
+
+  def test_OneTimeRestrictedAccessToken_getUserValue_wrong_values(self):
+    person = self._createPerson(self.new_id)
+    access_url = "http://exemple.com/foo"
+    access_method = "POST"
+    access_token = self._createOneTimeRestrictedAccessToken(self.new_id,
+                        person,
+                        access_method,
+                        access_url)
+    self.tic()
+    result = access_token.OneTimeRestrictedAccessToken_getUserValue()
+    self.assertEqual(result, None)
+
+    access_token.validate()
+    self.tic()
+
+    self.portal.REQUEST["REQUEST_METHOD"] = "GET"
+    self.portal.REQUEST["ACTUAL_URL"] = access_url
+
+    result = access_token.OneTimeRestrictedAccessToken_getUserValue()
+    self.assertEqual(result, None)
+
+    self.portal.REQUEST["ACTUAL_URL"] = "http://exemple.com/foo.bar"
+
+    result = access_token.OneTimeRestrictedAccessToken_getUserValue()
+    self.assertEqual(result, None)
+
+
+class TestERP5AccessTokenAlarm(AccessTokenTestCase):
+
+  def test_alarm_old_validated_restricted_access_token(self):
+    access_token = self.portal.access_token_module.newContent(
+      portal_type="One Time Restricted Access Token",
+    )
+    access_token.workflow_history['edit_workflow'] = [{
+        'comment':'Fake history',
+        'error_message': '',
+        'actor': 'ERP5TypeTestCase',
+        'state': 'current',
+        'time': DateTime('2012/11/15 11:11'),
+        'action': 'foo_action'
+        }]
+    self.portal.portal_workflow._jumpToStateFor(access_token, 'validated')
+    self.tic()
+
+    self.portal.portal_alarms.\
+      erp5_garbage_collect_one_time_restricted_access_token.activeSense()
+    self.tic()
+
+    self.assertEqual('invalidated', access_token.getValidationState())
+    self.assertEqual(
+        'Unused for 1 day.',
+        access_token.workflow_history['validation_workflow'][-1]['comment'])
+
+  def test_alarm_recent_validated_restricted_access_token(self):
+    access_token = self.portal.access_token_module.newContent(
+      portal_type="One Time Restricted Access Token",
+    )
+    self.portal.portal_workflow._jumpToStateFor(access_token, 'validated')
+    self.tic()
+
+    self.portal.portal_alarms.\
+      erp5_garbage_collect_one_time_restricted_access_token.activeSense()
+    self.tic()
+
+    self.assertEqual('validated', access_token.getValidationState())
+
+  def test_alarm_old_non_validated_restricted_access_token(self):
+    access_token = self.portal.access_token_module.newContent(
+      portal_type="One Time Restricted Access Token",
+    )
+    access_token.workflow_history['edit_workflow'] = [{
+        'comment':'Fake history',
+        'error_message': '',
+        'actor': 'ERP5TypeTestCase',
+        'state': 'current',
+        'time': DateTime('2012/11/15 11:11'),
+        'action': 'foo_action'
+        }]
+    self.tic()
+
+    self.portal.portal_alarms.\
+      erp5_garbage_collect_one_time_restricted_access_token.activeSense()
+    self.tic()
+
+    self.assertEqual('draft', access_token.getValidationState())
+
+
+class TestERP5DumbHTTPExtractionPlugin(AccessTokenTestCase):
+
+  test_id = 'test_erp5_dumb_http_extraction'
+
+  def generateNewId(self):
+    return str(self.portal.portal_ids.generateNewId(
+         id_group=('erp5_dumb_http_test_id')))
+
+  def afterSetUp(self):
+    """
+    This is ran before anything, used to set the environment
+    """
+    self.new_id = self.generateNewId()
+    self._setupDumbHTTPExtraction()
+    self.tic()
+
+  def do_fake_request(self, request_method, headers=None):
+    if headers is None:
+      headers = {}
+    __version__ = "0.1"
+    env={}
+    env['SERVER_NAME']='bobo.server'
+    env['SERVER_PORT']='80'
+    env['REQUEST_METHOD']=request_method
+    env['REMOTE_ADDR']='204.183.226.81 '
+    env['REMOTE_HOST']='bobo.remote.host'
+    env['HTTP_USER_AGENT']='Bobo/%s' % __version__
+    env['HTTP_HOST']='127.0.0.1'
+    env['SERVER_SOFTWARE']='Bobo/%s' % __version__
+    env['SERVER_PROTOCOL']='HTTP/1.0 '
+    env['HTTP_ACCEPT']='image/gif, image/x-xbitmap, image/jpeg, */* '
+    env['SERVER_HOSTNAME']='bobo.server.host'
+    env['GATEWAY_INTERFACE']='CGI/1.1 '
+    env['SCRIPT_NAME']='Main'
+    env.update(headers)
+    return HTTPRequest(StringIO.StringIO(), env, HTTPResponse())
+
+  def _setupDumbHTTPExtraction(self):
+    pas = self.portal.acl_users
+    access_extraction_list = [q for q in pas.objectValues() \
+        if q.meta_type == 'ERP5 Dumb HTTP Extraction Plugin']
+    if len(access_extraction_list) == 0:
+      dispacher = pas.manage_addProduct['ERP5Security']
+      dispacher.addERP5DumbHTTPExtractionPlugin(self.test_id)
+      getattr(pas, self.test_id).manage_activateInterfaces(
+        ('IExtractionPlugin',))
+    elif len(access_extraction_list) == 1:
+      self.test_id = access_extraction_list[0].getId()
+    elif len(access_extraction_list) > 1:
+      raise ValueError
+    self.commit()
+
+  def test_working_authentication(self):
+    self._createPerson(self.new_id, "test")
+    request = self.do_fake_request("GET", {"HTTP_AUTHORIZATION": "Basic " + base64.b64encode("%s:test" % self.new_id)})
+    ret = ERP5DumbHTTPExtractionPlugin("default_extraction").extractCredentials(request)
+    self.assertEqual(ret, {'login': self.new_id, 'password': 'test', 'remote_host': 'bobo.remote.host', 'remote_address': '204.183.226.81 '})
diff --git a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenSkins.xml b/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessToken.xml
similarity index 95%
rename from bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenSkins.xml
rename to bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessToken.xml
index ee8e0bbb804a770d2bef50290137fa0deababa8c..1e74dc9a62a0321337f5861a5b9929482973fbd7 100644
--- a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenSkins.xml
+++ b/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessToken.xml
@@ -14,7 +14,7 @@
         </item>
         <item>
             <key> <string>default_reference</string> </key>
-            <value> <string>testERP5AccessTokenSkins</string> </value>
+            <value> <string>testERP5AccessToken</string> </value>
         </item>
         <item>
             <key> <string>description</string> </key>
@@ -24,7 +24,7 @@
         </item>
         <item>
             <key> <string>id</string> </key>
-            <value> <string>test.erp5.testERP5AccessTokenSkins</string> </value>
+            <value> <string>test.erp5.testERP5AccessToken</string> </value>
         </item>
         <item>
             <key> <string>portal_type</string> </key>
diff --git a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenAlarm.py b/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenAlarm.py
deleted file mode 100644
index 76fadf3070360143164b64fb6a3c8fd4f5464b0f..0000000000000000000000000000000000000000
--- a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenAlarm.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright (c) 2002-2013 Nexedi SA and Contributors. All Rights Reserved.
-from DateTime import DateTime
-from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
-
-class TestERP5AccessTokenAlarm(ERP5TypeTestCase):
-
-  def getBusinessTemplateList(self):
-    return ('erp5_base',
-            'erp5_access_token')
-
-  def test_alarm_old_validated_restricted_access_token(self):
-    access_token = self.portal.access_token_module.newContent(
-      portal_type="One Time Restricted Access Token",
-    )
-    access_token.workflow_history['edit_workflow'] = [{
-        'comment':'Fake history',
-        'error_message': '',
-        'actor': 'ERP5TypeTestCase',
-        'state': 'current',
-        'time': DateTime('2012/11/15 11:11'),
-        'action': 'foo_action'
-        }]
-    self.portal.portal_workflow._jumpToStateFor(access_token, 'validated')
-    self.tic()
-
-    self.portal.portal_alarms.\
-      erp5_garbage_collect_one_time_restricted_access_token.activeSense()
-    self.tic()
-
-    self.assertEqual('invalidated', access_token.getValidationState())
-    self.assertEqual(
-        'Unused for 1 day.',
-        access_token.workflow_history['validation_workflow'][-1]['comment'])
-
-  def test_alarm_recent_validated_restricted_access_token(self):
-    access_token = self.portal.access_token_module.newContent(
-      portal_type="One Time Restricted Access Token",
-    )
-    self.portal.portal_workflow._jumpToStateFor(access_token, 'validated')
-    self.tic()
-
-    self.portal.portal_alarms.\
-      erp5_garbage_collect_one_time_restricted_access_token.activeSense()
-    self.tic()
-
-    self.assertEqual('validated', access_token.getValidationState())
-
-  def test_alarm_old_non_validated_restricted_access_token(self):
-    access_token = self.portal.access_token_module.newContent(
-      portal_type="One Time Restricted Access Token",
-    )
-    access_token.workflow_history['edit_workflow'] = [{
-        'comment':'Fake history',
-        'error_message': '',
-        'actor': 'ERP5TypeTestCase',
-        'state': 'current',
-        'time': DateTime('2012/11/15 11:11'),
-        'action': 'foo_action'
-        }]
-    self.tic()
-
-    self.portal.portal_alarms.\
-      erp5_garbage_collect_one_time_restricted_access_token.activeSense()
-    self.tic()
-
-    self.assertEqual('draft', access_token.getValidationState())
diff --git a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenAlarm.xml b/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenAlarm.xml
deleted file mode 100644
index a961f71a54aa899609299b8def8f95bbdd95bf5a..0000000000000000000000000000000000000000
--- a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenAlarm.xml
+++ /dev/null
@@ -1,123 +0,0 @@
-<?xml version="1.0"?>
-<ZopeData>
-  <record id="1" aka="AAAAAAAAAAE=">
-    <pickle>
-      <global name="Test Component" module="erp5.portal_type"/>
-    </pickle>
-    <pickle>
-      <dictionary>
-        <item>
-            <key> <string>_recorded_property_dict</string> </key>
-            <value>
-              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
-            </value>
-        </item>
-        <item>
-            <key> <string>default_reference</string> </key>
-            <value> <string>testERP5AccessTokenAlarm</string> </value>
-        </item>
-        <item>
-            <key> <string>description</string> </key>
-            <value>
-              <none/>
-            </value>
-        </item>
-        <item>
-            <key> <string>id</string> </key>
-            <value> <string>test.erp5.testERP5AccessTokenAlarm</string> </value>
-        </item>
-        <item>
-            <key> <string>portal_type</string> </key>
-            <value> <string>Test Component</string> </value>
-        </item>
-        <item>
-            <key> <string>sid</string> </key>
-            <value>
-              <none/>
-            </value>
-        </item>
-        <item>
-            <key> <string>text_content_error_message</string> </key>
-            <value>
-              <tuple/>
-            </value>
-        </item>
-        <item>
-            <key> <string>text_content_warning_message</string> </key>
-            <value>
-              <tuple/>
-            </value>
-        </item>
-        <item>
-            <key> <string>version</string> </key>
-            <value> <string>erp5</string> </value>
-        </item>
-        <item>
-            <key> <string>workflow_history</string> </key>
-            <value>
-              <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
-            </value>
-        </item>
-      </dictionary>
-    </pickle>
-  </record>
-  <record id="2" aka="AAAAAAAAAAI=">
-    <pickle>
-      <global name="PersistentMapping" module="Persistence.mapping"/>
-    </pickle>
-    <pickle>
-      <dictionary>
-        <item>
-            <key> <string>data</string> </key>
-            <value>
-              <dictionary/>
-            </value>
-        </item>
-      </dictionary>
-    </pickle>
-  </record>
-  <record id="3" aka="AAAAAAAAAAM=">
-    <pickle>
-      <global name="PersistentMapping" module="Persistence.mapping"/>
-    </pickle>
-    <pickle>
-      <dictionary>
-        <item>
-            <key> <string>data</string> </key>
-            <value>
-              <dictionary>
-                <item>
-                    <key> <string>component_validation_workflow</string> </key>
-                    <value>
-                      <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
-                    </value>
-                </item>
-              </dictionary>
-            </value>
-        </item>
-      </dictionary>
-    </pickle>
-  </record>
-  <record id="4" aka="AAAAAAAAAAQ=">
-    <pickle>
-      <global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
-    </pickle>
-    <pickle>
-      <tuple>
-        <none/>
-        <list>
-          <dictionary>
-            <item>
-                <key> <string>action</string> </key>
-                <value> <string>validate</string> </value>
-            </item>
-            <item>
-                <key> <string>validation_state</string> </key>
-                <value> <string>validated</string> </value>
-            </item>
-          </dictionary>
-        </list>
-      </tuple>
-    </pickle>
-  </record>
-</ZopeData>
diff --git a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenSkins.py b/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenSkins.py
deleted file mode 100644
index 6608f6033bc7bef032a0f16e30d35a35816c3d22..0000000000000000000000000000000000000000
--- a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5AccessTokenSkins.py
+++ /dev/null
@@ -1,256 +0,0 @@
-# Copyright (c) 2002-2013 Nexedi SA and Contributors. All Rights Reserved.
-
-from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
-import transaction
-
-class TestERP5AccessTokenSkins(ERP5TypeTestCase):
-
-  test_token_extraction_id = 'test_erp5_access_token_extraction'
-
-  def getBusinessTemplateList(self):
-    return ('erp5_base',
-            'erp5_access_token')
-
-  def generateNewId(self):
-    return str(self.portal.portal_ids.generateNewId(
-         id_group=('erp5_access_token_test_id')))
-
-  def afterSetUp(self):
-    """
-    This is ran before anything, used to set the environment
-    """
-    self.portal = self.getPortalObject()
-    self.new_id = self.generateNewId()
-    self._setupAccessTokenExtraction()
-    transaction.commit()
-    self.tic()
-
-  def _setupAccessTokenExtraction(self):
-    pas = self.portal.acl_users
-    access_extraction_list = [q for q in pas.objectValues() \
-        if q.meta_type == 'ERP5 Access Token Extraction Plugin']
-    if len(access_extraction_list) == 0:
-      dispacher = pas.manage_addProduct['ERP5Security']
-      dispacher.addERP5AccessTokenExtractionPlugin(self.test_token_extraction_id)
-      getattr(pas, self.test_token_extraction_id).manage_activateInterfaces(
-        ('IExtractionPlugin',))
-    elif len(access_extraction_list) == 1:
-      self.test_token_extraction_id = access_extraction_list[0].getId()
-    elif len(access_extraction_list) > 1:
-      raise ValueError
-    transaction.commit()
-
-  def _createPerson(self, new_id):
-    """Creates a person in person module, and returns the object, after
-    indexing is done. """
-    person_module = self.getPersonModule()
-    person = person_module.newContent(portal_type='Person',
-      user_id='TESTP-' + new_id)
-    person.newContent(portal_type = 'Assignment').open()
-    transaction.commit()
-    return person
-
-  def _getTokenCredential(self, request):
-    plugin = getattr(self.portal.acl_users, self.test_token_extraction_id)
-    return plugin.extractCredentials(request)
-
-  def _createRestrictedAccessToken(self, new_id, person, method, url_string):
-    access_token = self.portal.access_token_module.newContent(
-                    portal_type="Restricted Access Token",
-                    url_string=url_string,
-                    url_method=method,
-                  )
-    if person:
-      access_token.edit(agent_value=person)
-    return access_token
-
-  def _createOneTimeRestrictedAccessToken(self, new_id, person, method, url_string):
-    access_token = self.portal.access_token_module.newContent(
-                    portal_type="One Time Restricted Access Token",
-                    url_string=url_string,
-                    url_method=method,
-                  )
-    if person:
-      access_token.edit(agent_value=person)
-    return access_token
-
-  def test_working_token(self):
-    person = self.person = self._createPerson(self.new_id)
-    access_url = "http://exemple.com/foo"
-    access_method = "GET"
-    access_token = self._createRestrictedAccessToken(self.new_id,
-                        person,
-                        access_method,
-                        access_url)
-    access_token.validate()
-    self.tic()
-
-    self.portal.REQUEST.form["access_token"] = access_token.getId()
-    self.portal.REQUEST["REQUEST_METHOD"] = access_method
-    self.portal.REQUEST["ACTUAL_URL"] = access_url
-    self.portal.REQUEST.form["access_token_secret"] = access_token.getReference()
-
-    result = self._getTokenCredential(self.portal.REQUEST)
-    self.assertEqual(result.get('external_login'), person.Person_getUserId())
-
-  def test_bad_token(self):
-    person = self.person = self._createPerson(self.new_id)
-    access_url = "http://exemple.com/foo"
-    access_method = "GET"
-    access_token = self._createRestrictedAccessToken(self.new_id,
-                        person,
-                        access_method,
-                        access_url)
-    access_token.validate()
-    self.tic()
-
-    self.portal.REQUEST.form["access_token"] = "XYSYDT-YDTYSD"
-    self.portal.REQUEST["REQUEST_METHOD"] = access_method
-    self.portal.REQUEST["ACTUAL_URL"] = access_url
-    self.portal.REQUEST.form["access_token_secret"] = access_token.getReference()
-
-    result = self._getTokenCredential(self.portal.REQUEST)
-    self.assertEqual(result, {})
-
-  def test_RestrictedAccessToken_getExternalLogin(self):
-    person = self.person = self._createPerson(self.new_id)
-    access_url = "http://exemple.com/foo"
-    access_method = "GET"
-    access_token = self._createRestrictedAccessToken(self.new_id,
-                        person,
-                        access_method,
-                        access_url)
-    access_token.validate()
-    self.tic()
-
-    self.portal.REQUEST["REQUEST_METHOD"] = access_method
-    self.portal.REQUEST["ACTUAL_URL"] = access_url
-    self.portal.REQUEST.form["access_token_secret"] = access_token.getReference()
-
-    result = access_token.RestrictedAccessToken_getExternalLogin()
-
-    self.assertEqual(result, person.Person_getUserId())
-    self.assertEqual(access_token.getValidationState(), 'validated')
-
-  def test_RestrictedAccessToken_getExternalLogin_access_token_secret(self):
-    person = self.person = self._createPerson(self.new_id)
-    access_url = "http://exemple.com/foo"
-    access_method = "GET"
-    access_token = self._createRestrictedAccessToken(self.new_id,
-                        person,
-                        access_method,
-                        access_url)
-    access_token.validate()
-    self.tic()
-
-    self.portal.REQUEST["REQUEST_METHOD"] = access_method
-    self.portal.REQUEST["ACTUAL_URL"] = access_url
-
-    result = access_token.RestrictedAccessToken_getExternalLogin()
-    self.assertEqual(result, None)
-
-    self.portal.REQUEST.form["access_token_secret"] = "XYXYXYXY"
-    self.assertEqual(result, None)
-
-    self.portal.REQUEST.form["access_token_secret"] = access_token.getReference()
-
-    result = access_token.RestrictedAccessToken_getExternalLogin()
-
-    self.assertEqual(result, person.Person_getUserId())
-    self.assertEqual(access_token.getValidationState(), 'validated')
-
-  def test_RestrictedAccessToken_getExternalLogin_no_agent(self):
-    access_url = "http://exemple.com/foo"
-    access_method = "GET"
-    access_token = self._createRestrictedAccessToken(self.new_id,
-                        None,
-                        access_method,
-                        access_url)
-    access_token.validate()
-    self.tic()
-
-    self.portal.REQUEST["REQUEST_METHOD"] = access_method
-    self.portal.REQUEST["ACTUAL_URL"] = access_url
-    self.portal.REQUEST.form["access_token_secret"] = access_token.getReference()
-
-    result = access_token.RestrictedAccessToken_getExternalLogin()
-    self.assertEqual(result, None)
-
-  def test_RestrictedAccessToken_getExternalLogin_wrong_values(self):
-    person = self.person = self._createPerson(self.new_id)
-    access_url = "http://exemple.com/foo"
-    access_method = "GET"
-    access_token = self._createRestrictedAccessToken(self.new_id,
-                        person,
-                        access_method,
-                        access_url)
-    self.tic()
-    result = access_token.RestrictedAccessToken_getExternalLogin()
-    self.assertEqual(result, None)
-
-    access_token.validate()
-    self.tic()
-
-    self.portal.REQUEST["REQUEST_METHOD"] = "POST"
-    self.portal.REQUEST["ACTUAL_URL"] = access_url
-    self.portal.REQUEST.form["access_token_secret"] = access_token.getReference()
-
-    result = access_token.RestrictedAccessToken_getExternalLogin()
-    self.assertEqual(result, None)
-
-    self.portal.REQUEST["ACTUAL_URL"] = "http://exemple.com/foo.bar"
-
-    result = access_token.RestrictedAccessToken_getExternalLogin()
-    self.assertEqual(result, None)
-
-    access_token.invalidate()
-    self.tic()
-
-    result = access_token.RestrictedAccessToken_getExternalLogin()
-    self.assertEqual(result, None)
-
-
-  def test_OneTimeRestrictedAccessToken_getExternalLogin(self):
-    person = self.person = self._createPerson(self.new_id)
-    access_url = "http://exemple.com/foo"
-    access_method = "GET"
-    access_token = self._createOneTimeRestrictedAccessToken(self.new_id,
-                        person,
-                        access_method,
-                        access_url)
-    access_token.validate()
-    self.tic()
-
-    self.portal.REQUEST["REQUEST_METHOD"] = access_method
-    self.portal.REQUEST["ACTUAL_URL"] = access_url
-
-    result = access_token.OneTimeRestrictedAccessToken_getExternalLogin()
-
-    self.assertEqual(result, person.Person_getUserId())
-    self.assertEqual(access_token.getValidationState(), 'invalidated')
-
-  def test_OneTimeRestrictedAccessToken_getExternalLogin_wrong_values(self):
-    person = self.person = self._createPerson(self.new_id)
-    access_url = "http://exemple.com/foo"
-    access_method = "POST"
-    access_token = self._createOneTimeRestrictedAccessToken(self.new_id,
-                        person,
-                        access_method,
-                        access_url)
-    self.tic()
-    result = access_token.OneTimeRestrictedAccessToken_getExternalLogin()
-    self.assertEqual(result, None)
-
-    access_token.validate()
-    self.tic()
-
-    self.portal.REQUEST["REQUEST_METHOD"] = "GET"
-    self.portal.REQUEST["ACTUAL_URL"] = access_url
-
-    result = access_token.OneTimeRestrictedAccessToken_getExternalLogin()
-    self.assertEqual(result, None)
-
-    self.portal.REQUEST["ACTUAL_URL"] = "http://exemple.com/foo.bar"
-
-    result = access_token.OneTimeRestrictedAccessToken_getExternalLogin()
-    self.assertEqual(result, None)
diff --git a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5DumbHTTPExtractionPlugin.py b/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5DumbHTTPExtractionPlugin.py
deleted file mode 100644
index bd2d3fb3a65d4c554ef07625f517083a2da22c43..0000000000000000000000000000000000000000
--- a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5DumbHTTPExtractionPlugin.py
+++ /dev/null
@@ -1,111 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# Copyright (c) 2015 Nexedi SA and Contributors. All Rights Reserved.
-#                    Tristan Cavelier <tristan.cavelier@nexedi.com>
-#
-# WARNING: This program as such is intended to be used by professional
-# programmers who take the whole responsability of assessing all potential
-# consequences resulting from its eventual inadequacies and bugs
-# End users who are looking for a ready-to-use solution with commercial
-# garantees and support are strongly adviced to contract a Free Software
-# Service Company
-#
-# This program is Free Software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-##############################################################################
-
-from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
-from ZPublisher.HTTPRequest import HTTPRequest
-from ZPublisher.HTTPResponse import HTTPResponse
-from Products.ERP5Security.ERP5DumbHTTPExtractionPlugin import ERP5DumbHTTPExtractionPlugin
-import base64
-import transaction
-import StringIO
-
-class TestERP5DumbHTTPExtractionPlugin(ERP5TypeTestCase):
-
-  test_id = 'test_erp5_dumb_http_extraction'
-
-  def getBusinessTemplateList(self):
-    return ('erp5_base',)
-
-  def generateNewId(self):
-    return str(self.portal.portal_ids.generateNewId(
-         id_group=('erp5_dumb_http_test_id')))
-
-  def afterSetUp(self):
-    """
-    This is ran before anything, used to set the environment
-    """
-    self.portal = self.getPortalObject()
-    self.new_id = self.generateNewId()
-    self._setupDumbHTTPExtraction()
-    transaction.commit()
-    self.tic()
-
-  def do_fake_request(self, request_method, headers=None):
-    if headers is None:
-      headers = {}
-    __version__ = "0.1"
-    env={}
-    env['SERVER_NAME']='bobo.server'
-    env['SERVER_PORT']='80'
-    env['REQUEST_METHOD']=request_method
-    env['REMOTE_ADDR']='204.183.226.81 '
-    env['REMOTE_HOST']='bobo.remote.host'
-    env['HTTP_USER_AGENT']='Bobo/%s' % __version__
-    env['HTTP_HOST']='127.0.0.1'
-    env['SERVER_SOFTWARE']='Bobo/%s' % __version__
-    env['SERVER_PROTOCOL']='HTTP/1.0 '
-    env['HTTP_ACCEPT']='image/gif, image/x-xbitmap, image/jpeg, */* '
-    env['SERVER_HOSTNAME']='bobo.server.host'
-    env['GATEWAY_INTERFACE']='CGI/1.1 '
-    env['SCRIPT_NAME']='Main'
-    env.update(headers)
-    return HTTPRequest(StringIO.StringIO(), env, HTTPResponse())
-
-  def _setupDumbHTTPExtraction(self):
-    pas = self.portal.acl_users
-    access_extraction_list = [q for q in pas.objectValues() \
-        if q.meta_type == 'ERP5 Dumb HTTP Extraction Plugin']
-    if len(access_extraction_list) == 0:
-      dispacher = pas.manage_addProduct['ERP5Security']
-      dispacher.addERP5DumbHTTPExtractionPlugin(self.test_id)
-      getattr(pas, self.test_id).manage_activateInterfaces(
-        ('IExtractionPlugin',))
-    elif len(access_extraction_list) == 1:
-      self.test_id = access_extraction_list[0].getId()
-    elif len(access_extraction_list) > 1:
-      raise ValueError
-    transaction.commit()
-
-  def _createPerson(self, new_id, password=None):
-    """Creates a person in person module, and returns the object, after
-    indexing is done. """
-    person_module = self.getPersonModule()
-    person = person_module.newContent(portal_type='Person',
-      reference='TESTP-' + new_id)
-    if password:
-      person.setPassword(password)
-    person.newContent(portal_type = 'Assignment').open()
-    transaction.commit()
-    return person
-
-  def test_working_authentication(self):
-    self._createPerson(self.new_id, "test")
-    request = self.do_fake_request("GET", {"HTTP_AUTHORIZATION": "Basic " + base64.b64encode("%s:test" % self.new_id)})
-    ret = ERP5DumbHTTPExtractionPlugin("default_extraction").extractCredentials(request)
-    self.assertEqual(ret, {'login': self.new_id, 'password': 'test', 'remote_host': 'bobo.remote.host', 'remote_address': '204.183.226.81 '})
diff --git a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5DumbHTTPExtractionPlugin.xml b/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5DumbHTTPExtractionPlugin.xml
deleted file mode 100644
index 6c6f9f84fc517d6b3f26f8b4280fcd5abe954a28..0000000000000000000000000000000000000000
--- a/bt5/erp5_access_token/TestTemplateItem/portal_components/test.erp5.testERP5DumbHTTPExtractionPlugin.xml
+++ /dev/null
@@ -1,123 +0,0 @@
-<?xml version="1.0"?>
-<ZopeData>
-  <record id="1" aka="AAAAAAAAAAE=">
-    <pickle>
-      <global name="Test Component" module="erp5.portal_type"/>
-    </pickle>
-    <pickle>
-      <dictionary>
-        <item>
-            <key> <string>_recorded_property_dict</string> </key>
-            <value>
-              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
-            </value>
-        </item>
-        <item>
-            <key> <string>default_reference</string> </key>
-            <value> <string>testERP5DumbHTTPExtractionPlugin</string> </value>
-        </item>
-        <item>
-            <key> <string>description</string> </key>
-            <value>
-              <none/>
-            </value>
-        </item>
-        <item>
-            <key> <string>id</string> </key>
-            <value> <string>test.erp5.testERP5DumbHTTPExtractionPlugin</string> </value>
-        </item>
-        <item>
-            <key> <string>portal_type</string> </key>
-            <value> <string>Test Component</string> </value>
-        </item>
-        <item>
-            <key> <string>sid</string> </key>
-            <value>
-              <none/>
-            </value>
-        </item>
-        <item>
-            <key> <string>text_content_error_message</string> </key>
-            <value>
-              <tuple/>
-            </value>
-        </item>
-        <item>
-            <key> <string>text_content_warning_message</string> </key>
-            <value>
-              <tuple/>
-            </value>
-        </item>
-        <item>
-            <key> <string>version</string> </key>
-            <value> <string>erp5</string> </value>
-        </item>
-        <item>
-            <key> <string>workflow_history</string> </key>
-            <value>
-              <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
-            </value>
-        </item>
-      </dictionary>
-    </pickle>
-  </record>
-  <record id="2" aka="AAAAAAAAAAI=">
-    <pickle>
-      <global name="PersistentMapping" module="Persistence.mapping"/>
-    </pickle>
-    <pickle>
-      <dictionary>
-        <item>
-            <key> <string>data</string> </key>
-            <value>
-              <dictionary/>
-            </value>
-        </item>
-      </dictionary>
-    </pickle>
-  </record>
-  <record id="3" aka="AAAAAAAAAAM=">
-    <pickle>
-      <global name="PersistentMapping" module="Persistence.mapping"/>
-    </pickle>
-    <pickle>
-      <dictionary>
-        <item>
-            <key> <string>data</string> </key>
-            <value>
-              <dictionary>
-                <item>
-                    <key> <string>component_validation_workflow</string> </key>
-                    <value>
-                      <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
-                    </value>
-                </item>
-              </dictionary>
-            </value>
-        </item>
-      </dictionary>
-    </pickle>
-  </record>
-  <record id="4" aka="AAAAAAAAAAQ=">
-    <pickle>
-      <global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/>
-    </pickle>
-    <pickle>
-      <tuple>
-        <none/>
-        <list>
-          <dictionary>
-            <item>
-                <key> <string>action</string> </key>
-                <value> <string>validate</string> </value>
-            </item>
-            <item>
-                <key> <string>validation_state</string> </key>
-                <value> <string>validated</string> </value>
-            </item>
-          </dictionary>
-        </list>
-      </tuple>
-    </pickle>
-  </record>
-</ZopeData>
diff --git a/bt5/erp5_access_token/bt/template_test_id_list b/bt5/erp5_access_token/bt/template_test_id_list
index 3f19acd9e28344735d8c3fb584e1541505d6aa16..0279f3442a9ccea4b7fb1d546c6354926a5df1bc 100644
--- a/bt5/erp5_access_token/bt/template_test_id_list
+++ b/bt5/erp5_access_token/bt/template_test_id_list
@@ -1,3 +1 @@
-test.erp5.testERP5AccessTokenAlarm
-test.erp5.testERP5AccessTokenSkins
-test.erp5.testERP5DumbHTTPExtractionPlugin
\ No newline at end of file
+test.erp5.testERP5AccessToken
\ No newline at end of file
diff --git a/product/ERP5Security/ERP5AccessTokenExtractionPlugin.py b/product/ERP5Security/ERP5AccessTokenExtractionPlugin.py
index da3279111b1c386629083f2915f4aa6ecb7d4c75..793a59efe38e526cf5855b961d6447852b1e7e01 100644
--- a/product/ERP5Security/ERP5AccessTokenExtractionPlugin.py
+++ b/product/ERP5Security/ERP5AccessTokenExtractionPlugin.py
@@ -59,35 +59,38 @@ class ERP5AccessTokenExtractionPlugin(BasePlugin):
   #ILoginPasswordHostExtractionPlugin#
   ####################################
   security.declarePrivate('extractCredentials')
-  @UnrestrictedMethod
   def extractCredentials(self, request):
-    """ Extract CookieHash credentials from the request header. """
+    """ Extract credentials from the request header. """
     creds = {}
-    # XXX Extract from HTTP Header, URL parameter are hardcoded.
-    # More flexible way would be to configure on the portal type level
-    token = request.getHeader("X-ACCESS-TOKEN", None)
-    if token is None:
-      token = request.form.get("access_token", None)
-    if token is not None:
+    # Extract token from HTTP Header
+    token = request.getHeader("X-ACCESS-TOKEN", request.form.get("access_token", None))
+    if token:
+      creds['erp5_access_token_id'] = token
+      creds['remote_host'] = request.get('REMOTE_HOST', '')
+      try:
+        creds['remote_address'] = request.getClientAddr()
+      except AttributeError:
+        creds['remote_address'] = request.get('REMOTE_ADDR', '')
+    return creds
+
+  #######################
+  #IAuthenticationPlugin#
+  #######################
+  security.declarePrivate('authenticateCredentials')
+  @UnrestrictedMethod
+  def authenticateCredentials(self, credentials):
+    """ Map credentials to a user ID. """
+    if 'erp5_access_token_id' in credentials:
+      erp5_access_token_id = credentials['erp5_access_token_id']
       token_document = self.getPortalObject().access_token_module.\
-                                        _getOb(token, None)
-      # Access Token should be validated
-      # Check restricted access of URL
-      # Extract login information
+                     _getOb(erp5_access_token_id, None)
       if token_document is not None:
-        external_login = None
-        method = token_document._getTypeBasedMethod('getExternalLogin')
+        method = token_document._getTypeBasedMethod('getUserValue')
         if method is not None:
-          external_login = method()
-
-        if external_login is not None:
-          creds['external_login'] = external_login
-          creds['remote_host'] = request.get('REMOTE_HOST', '')
-          try:
-            creds['remote_address'] = request.getClientAddr()
-          except AttributeError:
-            creds['remote_address'] = request.get('REMOTE_ADDR', '')
-    return creds
+          user_value = method()
+          if user_value is not None:
+            return (user_value.getUserId(), token_document.getRelativeUrl())
+
 
 #Form for new plugin in ZMI
 manage_addERP5AccessTokenExtractionPluginForm = PageTemplateFile(
@@ -109,6 +112,7 @@ def addERP5AccessTokenExtractionPlugin(dispatcher, id, title=None, REQUEST=None)
 
 #List implementation of class
 classImplements(ERP5AccessTokenExtractionPlugin,
-                plugins.ILoginPasswordHostExtractionPlugin
-               )
+                plugins.ILoginPasswordHostExtractionPlugin,
+                plugins.IAuthenticationPlugin,
+                )
 InitializeClass(ERP5AccessTokenExtractionPlugin)