diff --git a/Module.php b/Module.php
index 66d741736b3ebcd1bb55315688b74d98a08f9cf4..0172675d30debb1aba2b9b8fb1e049a781afded0 100644
--- a/Module.php
+++ b/Module.php
@@ -9,7 +9,7 @@ use Zend\EventManager\EventInterface;
 use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
 use Zend\ModuleManager\Feature\ConfigProviderInterface;
 use Zend\ModuleManager\Feature\ServiceProviderInterface;
-use Zend\ServiceManager\Exception\ServiceNotFoundException;
+use Zend\ModuleManager\ModuleManager;
 use Zend\ServiceManager\ServiceLocatorInterface;
 use Zend\View\Helper\Navigation;
 use ZfcUser\Form\Login;
@@ -69,14 +69,12 @@ class Module implements AutoloaderProviderInterface, ConfigProviderInterface, Se
         /* @var $services \Zend\ServiceManager\ServiceManager */
         $services = $application->getServiceManager();
 
-        // transmission des ACL aux aides de vue de navigation
-        try {
+        if ($services->has('BjyAuthorize\Service\Authorize')) {
+            // transmission des ACL aux aides de vue de navigation
             $authorizeService = $services->get('BjyAuthorize\Service\Authorize');
             /* @var $authorizeService \BjyAuthorize\Service\Authorize */
             Navigation::setDefaultAcl($authorizeService->getAcl());
             Navigation::setDefaultRole($authorizeService->getIdentity());
-        } catch (ServiceNotFoundException $snfe) {
-            // pas de module BjyAuthorize : pas d'ACL
         }
 
         /* @var $options ModuleOptions */
diff --git a/config/module.config.php b/config/module.config.php
index 14419ef267ad94a699a62d6b01505ca5ec7c71bf..e031665b4a57ee2e64430bff0aad0f6bb931c541 100644
--- a/config/module.config.php
+++ b/config/module.config.php
@@ -9,6 +9,7 @@ use UnicaenAuth\Controller\UtilisateurControllerFactory;
 use UnicaenAuth\Form\Droits\RoleFormFactory;
 use UnicaenAuth\Guard\PrivilegeControllerFactory;
 use UnicaenAuth\Guard\PrivilegeRouteFactory;
+use UnicaenAuth\ORM\Event\Listeners\HistoriqueListenerFactory;
 use UnicaenAuth\Provider\Rule\PrivilegeRuleProviderFactory;
 use UnicaenAuth\Service\ShibService;
 use UnicaenAuth\Service\ShibServiceFactory;
@@ -490,6 +491,9 @@ return [
             'UnicaenAuth\Guard\PrivilegeController'   => PrivilegeControllerFactory::class,
             'UnicaenAuth\Guard\PrivilegeRoute'        => PrivilegeRouteFactory::class,
             'UnicaenAuth\Provider\Rule\PrivilegeRuleProvider' => PrivilegeRuleProviderFactory::class,
+
+            'UnicaenApp\HistoriqueListener' => HistoriqueListenerFactory::class,
+            'UnicaenAuth\HistoriqueListener' => HistoriqueListenerFactory::class,
         ],
         'lazy_services' => [
             // Mapping services to their class names is required since the ServiceManager is not a declarative DIC.
diff --git a/src/UnicaenAuth/Authentication/Adapter/AbstractFactory.php b/src/UnicaenAuth/Authentication/Adapter/AbstractFactory.php
index 629eca68cd3f5c0c0986a94d175d0ccb8c38d0e2..6a32bd9776f9ed6e46266898316d6fcccf929173 100644
--- a/src/UnicaenAuth/Authentication/Adapter/AbstractFactory.php
+++ b/src/UnicaenAuth/Authentication/Adapter/AbstractFactory.php
@@ -104,7 +104,7 @@ class AbstractFactory implements AbstractFactoryInterface
                 $userService = $container->get('unicaen-auth_user_service');
                 $adapter->setUserService($userService);
 
-                /** @var TreeRouteStack $router */
+                /** @var mixed $router */
                 $router = $container->get('router');
                 $adapter->setRouter($router);
 
diff --git a/src/UnicaenAuth/Authentication/Adapter/Cas.php b/src/UnicaenAuth/Authentication/Adapter/Cas.php
index d73b9cf6f4c4d57a19722122f19d430b03b6b26d..fb3e21a5e80213df0f8ac4abeb9c21703880c876 100644
--- a/src/UnicaenAuth/Authentication/Adapter/Cas.php
+++ b/src/UnicaenAuth/Authentication/Adapter/Cas.php
@@ -2,6 +2,7 @@
 
 namespace UnicaenAuth\Authentication\Adapter;
 
+use Exception;
 use phpCAS;
 use UnicaenApp\Mapper\Ldap\People as LdapPeopleMapper;
 use UnicaenAuth\Options\ModuleOptions;
@@ -13,7 +14,8 @@ use Zend\EventManager\EventInterface;
 use Zend\EventManager\EventManager;
 use Zend\EventManager\EventManagerAwareInterface;
 use Zend\EventManager\EventManagerInterface;
-use Zend\Router\Http\TreeRouteStack;
+use Zend\Router\RouteInterface;
+use Zend\Router\RouteStackInterface;
 use ZfcUser\Authentication\Adapter\AbstractAdapter;
 use ZfcUser\Authentication\Adapter\ChainableAdapter;
 
@@ -63,14 +65,14 @@ class Cas extends AbstractAdapter implements EventManagerAwareInterface
     }
 
     /**
-     * @var TreeRouteStack
+     * @var RouteInterface
      */
     private $router;
 
     /**
-     * @param TreeRouteStack $router
+     * @param RouteInterface $router
      */
-    public function setRouter(TreeRouteStack $router)
+    public function setRouter(RouteInterface $router)
     {
         $this->router = $router;
     }
@@ -263,10 +265,14 @@ class Cas extends AbstractAdapter implements EventManagerAwareInterface
     }
 
     /**
-     * @param TreeRouteStack $router
+     * @param RouteInterface $router
      */
-    public function reconfigureRoutesForCasAuth(TreeRouteStack $router)
+    public function reconfigureRoutesForCasAuth(RouteInterface $router)
     {
+        if(!$router instanceof RouteStackInterface) {
+            return;
+        }
+
         $router->addRoutes([
             // remplace les routes existantes (cf. config du module)
             'zfcuser' => [
diff --git a/src/UnicaenAuth/Controller/UtilisateurController.php b/src/UnicaenAuth/Controller/UtilisateurController.php
index ca94363b6b6fca450099ce6004224cb843258f6a..0c1aee57170c4e51cc048f605bb48978b957fd50 100644
--- a/src/UnicaenAuth/Controller/UtilisateurController.php
+++ b/src/UnicaenAuth/Controller/UtilisateurController.php
@@ -7,8 +7,8 @@ use UnicaenApp\Mapper\Ldap\People as LdapPeopleMapper;
 use UnicaenAuth\Entity\Db\AbstractUser;
 use UnicaenAuth\Entity\Ldap\People;
 use UnicaenAuth\Entity\Shibboleth\ShibUser;
+use UnicaenAuth\Formatter\RoleFormatter;
 use UnicaenAuth\Options\ModuleOptions;
-use UnicaenAuth\Service\ShibService;
 use UnicaenAuth\Service\Traits\ShibServiceAwareTrait;
 use UnicaenAuth\Service\Traits\UserContextServiceAwareTrait;
 use UnicaenAuth\Service\UserContext;
@@ -16,7 +16,7 @@ use Zend\Authentication\AuthenticationService;
 use Zend\Http\Request;
 use Zend\Http\Response;
 use Zend\Mvc\Controller\AbstractActionController;
-use ZfcUser\Mapper\User as UserMapper;
+use ZfcUser\Mapper\UserInterface;
 
 /**
  * @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>
@@ -40,7 +40,7 @@ class UtilisateurController extends AbstractActionController
     }
 
     /**
-     * @var UserMapper
+     * @var UserInterface
      */
     private $userMapper;
 
@@ -55,9 +55,9 @@ class UtilisateurController extends AbstractActionController
     protected $options;
 
     /**
-     * @param UserMapper $userMapper
+     * @param UserInterface $userMapper
      */
-    public function setUserMapper(UserMapper $userMapper)
+    public function setUserMapper(UserInterface $userMapper)
     {
         $this->userMapper = $userMapper;
     }
@@ -78,15 +78,6 @@ class UtilisateurController extends AbstractActionController
         $this->options = $options;
     }
 
-    /**
-     * @param UserContext $userContextService
-     * @deprecated Utiliser UserContextServiceAwareTrait::setServiceUserContext() à la place, svp.
-     */
-    public function setUserContextService(UserContext $userContextService)
-    {
-        $this->serviceUserContext = $userContextService;
-    }
-
     /**
      * Traite les requêtes AJAX POST de sélection d'un profil utilisateur.
      * La sélection est mémorisé en session par le service AuthUserContext.
@@ -111,8 +102,11 @@ class UtilisateurController extends AbstractActionController
         }
 
         if ($addFlashMessage) {
-            $selectedRole = $this->serviceUserContext->getSelectedIdentityRoleToString();
-            $message = sprintf("Vous endossez à présent le profil utilisateur <strong>%s</strong>.", $selectedRole);
+            $selectedRole = $this->serviceUserContext->getSelectedIdentityRole();
+            $message = sprintf(
+                "Vous endossez à présent le rôle utilisateur '<strong>%s</strong>'.",
+                (new RoleFormatter())->format($selectedRole)
+            );
             $this->flashMessenger()->setNamespace('UnicaenAuth/success')->addMessage($message);
         }
 
@@ -212,7 +206,7 @@ class UtilisateurController extends AbstractActionController
     }
 
     /**
-     * @return UserMapper
+     * @return UserInterface
      */
     public function getUserMapper()
     {
diff --git a/src/UnicaenAuth/Controller/UtilisateurControllerFactory.php b/src/UnicaenAuth/Controller/UtilisateurControllerFactory.php
index 06216028a5271520628b83c463fbf8daf89791ba..f406b54f46f4a3bee63c55f5ef3973cdd79d9c5a 100644
--- a/src/UnicaenAuth/Controller/UtilisateurControllerFactory.php
+++ b/src/UnicaenAuth/Controller/UtilisateurControllerFactory.php
@@ -8,7 +8,7 @@ use UnicaenAuth\Options\ModuleOptions;
 use UnicaenAuth\Service\ShibService;
 use UnicaenAuth\Service\UserContext;
 use Zend\Authentication\AuthenticationService;
-use ZfcUser\Mapper\UserInterface as UserMapper;
+use ZfcUser\Mapper\UserInterface;
 
 class UtilisateurControllerFactory
 {
@@ -18,7 +18,7 @@ class UtilisateurControllerFactory
      */
     public function __invoke(ContainerInterface $container)
     {
-        /** @var UserMapper $mapper */
+        /** @var UserInterface $mapper */
         $userMapper = $container->get('zfcuser_user_mapper');
 
         /** @var AuthenticationService $authenticationService */
diff --git a/src/UnicaenAuth/Formatter/RoleFormatter.php b/src/UnicaenAuth/Formatter/RoleFormatter.php
index 0f5d966352eb0fdfc30ac42d04aff5c73fd744e0..944ce8821403eefb0f21abecc09b0c5a9642931f 100644
--- a/src/UnicaenAuth/Formatter/RoleFormatter.php
+++ b/src/UnicaenAuth/Formatter/RoleFormatter.php
@@ -2,41 +2,66 @@
 
 namespace UnicaenAuth\Formatter;
 
-use Zend\Permissions\Rbac\RoleInterface;
+use Zend\Permissions\Acl\Role\RoleInterface;
 
 class RoleFormatter
 {
     /**
-     * Retourne le rôle utilisateur spécifié au format littéral.
+     * Retourne le rôle spécifié au format littéral.
      *
-     * @param $role
+     * @param object|RoleInterface|string $role
      * @return string
+     *
+     * @see formatOne()
      */
     public function format($role)
     {
-        return $this->roleToString($role);
+        return $this->formatOne($role);
     }
 
     /**
-     * Retourne le rôle utilisateur spécifié au format littéral.
+     * Retourne le rôle spécifié au format littéral.
      *
      * @param object|RoleInterface|string $role
      * @return string
      */
-    private function roleToString($role)
+    public function formatOne($role)
     {
-        $string = '?';
+        $formattedRole = '?';
 
-        if (is_object($role) && method_exists($role, '__toString')) {
-            $string = (string) $role;
-        }
-        elseif ($role instanceof RoleInterface) {
-            $string = $role->getRoleId();
+        if ($role instanceof RoleInterface) {
+            $formattedRole = $role->getRoleId();
         }
         elseif (is_string($role)) {
-            $string = $role;
+            $formattedRole = (string) $role;
+        }
+        elseif (is_object($role) && method_exists($role, '__toString')) {
+            $formattedRole = $role;
+        }
+
+        return $formattedRole;
+    }
+
+    /**
+     * Retourne les rôles spécifiés au format littéral.
+     *
+     * @param object[]|RoleInterface[]|string[] $roles
+     * @return string[]
+     */
+    public function formatMany(array $roles)
+    {
+        $formattedRoles = [];
+
+        foreach ($roles as $key => $role) {
+            if ($role instanceof RoleInterface) {
+                $key = $role->getRoleId();
+            }
+            elseif (is_string($role)) {
+                $key = $role;
+            }
+            $formattedRoles[$key] = $this->formatOne($role);
         }
 
-        return $string;
+        return $formattedRoles;
     }
 }
\ No newline at end of file
diff --git a/src/UnicaenAuth/Mouchard/MouchardCompleterAuth.php b/src/UnicaenAuth/Mouchard/MouchardCompleterAuth.php
index 526079b0c3bc88c17849cb1bbe8c38df40f21b89..683d2a2ad667519123d43db4d360c45b97b932dc 100644
--- a/src/UnicaenAuth/Mouchard/MouchardCompleterAuth.php
+++ b/src/UnicaenAuth/Mouchard/MouchardCompleterAuth.php
@@ -17,17 +17,18 @@ class MouchardCompleterAuth implements MouchardCompleterInterface
     use UserContextServiceAwareTrait;
 
     /**
+     * @param MouchardMessage $message
      * @return $this
      */
     public function complete(MouchardMessage $message)
     {
-        $user = $this->getServiceUserContext()->getDbUser();
+        $user = $this->serviceUserContext->getDbUser();
         if ($user){
             $message->setUser($user->getDisplayName());
             $message->setLogin($user->getUsername());
         }
 
-        $message->setRole((string)$this->getServiceUserContext()->getSelectedIdentityRole());
+        $message->setRole((string)$this->serviceUserContext->getSelectedIdentityRole());
 
         return $this;
     }
diff --git a/src/UnicaenAuth/ORM/Event/Listeners/HistoriqueListener.php b/src/UnicaenAuth/ORM/Event/Listeners/HistoriqueListener.php
new file mode 100644
index 0000000000000000000000000000000000000000..36b3a979c47ee7da186044f3e82c12e15abdbdcc
--- /dev/null
+++ b/src/UnicaenAuth/ORM/Event/Listeners/HistoriqueListener.php
@@ -0,0 +1,166 @@
+<?php
+
+namespace UnicaenAuth\ORM\Event\Listeners;
+
+use Doctrine\Common\EventSubscriber;
+use Doctrine\ORM\Event\LifecycleEventArgs;
+use Doctrine\ORM\Event\PreUpdateEventArgs;
+use Doctrine\ORM\Events;
+use RuntimeException;
+use UnicaenApp\Entity\HistoriqueAwareInterface;
+use UnicaenAuth\Entity\Db\AbstractUser;
+use Zend\Authentication\AuthenticationService;
+
+/**
+ * Listener Doctrine.
+ *
+ * Renseigne si besoin l'heure et l'auteur de la création/modification
+ * de toute entité dont la classe implémente HistoriqueAwareInterface.
+ *
+ * Déclenchement : avant que l'enregistrement ne soit persisté (création) ou mis à jour (update).
+ *
+ * @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr>
+ * @see HistoriqueAwareInterface
+ */
+class HistoriqueListener implements EventSubscriber
+{
+    /**
+     * @var AuthenticationService
+     */
+    private $authenticationService;
+
+    /**
+     * @var mixed
+     */
+    protected $identity;
+
+    /**
+     * @param AuthenticationService $authenticationService
+     */
+    public function setAuthenticationService(AuthenticationService $authenticationService)
+    {
+        $this->authenticationService = $authenticationService;
+    }
+
+    /**
+     * @param LifecycleEventArgs $args
+     * @throws RuntimeException Aucun utilisateur disponible pour en faire l'auteur de la création/modification
+     */
+    protected function updateHistorique(LifecycleEventArgs $args)
+    {
+        $entity = $args->getEntity();
+
+        // l'entité doit implémenter l'interface requise
+        if (! $entity instanceof HistoriqueAwareInterface) {
+            return;
+        }
+
+        $now = new \DateTime();
+
+        if (null === $entity->getHistoCreation()) {
+            $entity->setHistoCreation($now);
+        }
+
+        // on tente d'abord d'obtenir l'utilisateur connecté pour en faire l'auteur de la création/modification.
+        $user = $this->getAuthenticatedUser();
+        // si aucun utilisateur connecté n'est disponible, on utilise l'éventuel auteur existant
+        if (null === $user) {
+            $user = $entity->getHistoCreateur();
+        }
+        // si nous ne disposons d'aucun utilisateur, basta!
+        if (null === $user) {
+            throw new RuntimeException("Aucun utilisateur disponible pour en faire l'auteur de la création/modification.");
+        }
+
+        if (null === $entity->getHistoCreateur()) {
+            $entity->setHistoCreateur($user);
+        }
+
+        $entity->setHistoModificateur($user);
+        $entity->setHistoModification($now);
+        /* ce bloc a été mis en commentaire car il est inutile: cf. 2 lignes précédentes !
+        if (null === $entity->getHistoDestruction() && null === $entity->getHistoDestructeur()) {
+            $entity
+                ->setHistoModification($now)
+                ->setHistoModificateur($user);
+        }
+        */
+
+        if (null !== $entity->getHistoDestruction() && null === $entity->getHistoDestructeur()) {
+            $entity->setHistoDestructeur($user);
+        }
+    }
+
+    /**
+     * Recherche l'utilisateur connecté pour l'utiliser comme auteur de la création/modification.
+     *
+     * @return AbstractUser
+     */
+    private function getAuthenticatedUser()
+    {
+        $user = null;
+
+        if (($identity = $this->getIdentity())) {
+            if (isset($identity['db']) && $identity['db'] instanceof AbstractUser) {
+                /* @var $user AbstractUser */
+                $user = $identity['db'];
+            }
+        }
+
+        return $user;
+    }
+
+    /**
+     * @param LifecycleEventArgs $args
+     */
+    public function prePersist(LifecycleEventArgs $args)
+    {
+        $this->updateHistorique($args);
+    }
+
+    /**
+     * @param PreUpdateEventArgs $args
+     */
+    public function preUpdate(PreUpdateEventArgs $args)
+    {
+        $this->updateHistorique($args);
+    }
+
+    /**
+     * Injecte l'identité authentifiée courante.
+     *
+     * @param mixed $identity
+     * @return self
+     */
+    public function setIdentity($identity)
+    {
+        $this->identity = $identity;
+
+        return $this;
+    }
+
+    /**
+     * Retourne l'identité authentifiée courante.
+     *
+     * @return mixed
+     */
+    public function getIdentity()
+    {
+        if (null === $this->identity) {
+            $authenticationService = $this->authenticationService;
+            if ($authenticationService->hasIdentity()) {
+                $this->identity = $authenticationService->getIdentity();
+            }
+        }
+
+        return $this->identity;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getSubscribedEvents()
+    {
+        return [Events::prePersist, Events::preUpdate];
+    }
+}
\ No newline at end of file
diff --git a/src/UnicaenAuth/ORM/Event/Listeners/HistoriqueListenerFactory.php b/src/UnicaenAuth/ORM/Event/Listeners/HistoriqueListenerFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..c35c5e5bbfba86bce8e9755e540de6e984abd832
--- /dev/null
+++ b/src/UnicaenAuth/ORM/Event/Listeners/HistoriqueListenerFactory.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace UnicaenAuth\ORM\Event\Listeners;
+
+use Interop\Container\ContainerInterface;
+use Zend\Authentication\AuthenticationService;
+use Zend\ServiceManager\FactoryInterface;
+use Zend\ServiceManager\ServiceLocatorInterface;
+
+/**
+ * Description of MouchardServiceFactory
+ *
+ * @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
+ */
+class HistoriqueListenerFactory implements FactoryInterface
+{
+    public function createService(ServiceLocatorInterface $serviceLocator)
+    {
+        return $this->__invoke($serviceLocator, '?');
+    }
+
+    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
+    {
+        /** @var AuthenticationService $authenticationService */
+        $authenticationService = $container->get('Zend\Authentication\AuthenticationService');
+
+        $listener = new HistoriqueListener();
+        $listener->setAuthenticationService($authenticationService);
+
+        return $listener;
+    }
+}
diff --git a/src/UnicaenAuth/Service/AuthorizeService.php b/src/UnicaenAuth/Service/AuthorizeService.php
index eea0e75a5ed92aa25646ab12a9173684da968dcd..175110b3c0d08d63d4d1c50f99c3b7af0cddf9e0 100644
--- a/src/UnicaenAuth/Service/AuthorizeService.php
+++ b/src/UnicaenAuth/Service/AuthorizeService.php
@@ -34,7 +34,7 @@ class AuthorizeService extends \BjyAuthorize\Service\Authorize
         if ($this->loading) return 'bjyauthorize-identity';
 
         // on retourne par défaut le rôle sélectionné
-        $role = $this->getServiceUserContext()->getSelectedIdentityRole();
+        $role = $this->serviceUserContext->getSelectedIdentityRole();
         if ($role) return $role;
 
         $roles = $this->getIdentityProvider()->getIdentityRoles();
diff --git a/src/UnicaenAuth/Service/ShibService.php b/src/UnicaenAuth/Service/ShibService.php
index 6ec2d8bce4cbed21df426ccaa6dde1717a660ec8..eee2d0f6e811d9343ba3d7b3a7a29303dd153160 100644
--- a/src/UnicaenAuth/Service/ShibService.php
+++ b/src/UnicaenAuth/Service/ShibService.php
@@ -470,8 +470,8 @@ EOS;
                         'options' => [
                             'route' => '/connexion',
                             'defaults' => [
-                                'controller' => 'zfcuser',
-                                'action'     => 'login',
+                                'controller' => 'zfcuser', // NB: lorsque l'auth Shibboleth est activée, la page propose
+                                'action'     => 'login',   //     2 possibilités d'auth : LDAP et Shibboleth.
                             ],
                         ],
                     ],
diff --git a/src/UnicaenAuth/Service/Traits/UserContextServiceAwareTrait.php b/src/UnicaenAuth/Service/Traits/UserContextServiceAwareTrait.php
index caf58573fc3177161a9ccb8af519b99d230894bd..3ebb97883d39f5ca6cd2402b1423f1fa547eaed4 100644
--- a/src/UnicaenAuth/Service/Traits/UserContextServiceAwareTrait.php
+++ b/src/UnicaenAuth/Service/Traits/UserContextServiceAwareTrait.php
@@ -3,25 +3,19 @@
 namespace UnicaenAuth\Service\Traits;
 
 use UnicaenAuth\Service\UserContext;
-use RuntimeException;
 
 /**
- * Description of UserContextServiceAwareTrait
- *
- * @author Laurent LÉCLUSE <laurent.lecluse at unicaen.fr>
+ * @author Unicaen
  */
 trait UserContextServiceAwareTrait
 {
     /**
      * @var UserContext
      */
-    private $serviceUserContext;
-
-
+    protected $serviceUserContext;
 
     /**
      * @param UserContext $serviceUserContext
-     *
      * @return self
      */
     public function setServiceUserContext(UserContext $serviceUserContext)
@@ -30,15 +24,4 @@ trait UserContextServiceAwareTrait
 
         return $this;
     }
-
-
-
-    /**
-     * @return UserContext
-     * @throws RuntimeException
-     */
-    public function getServiceUserContext()
-    {
-        return $this->serviceUserContext;
-    }
 }
\ No newline at end of file
diff --git a/src/UnicaenAuth/Service/UserContextFactory.php b/src/UnicaenAuth/Service/UserContextFactory.php
index 245ea1bc52b4a8499c94dddbe33852e24ac13d53..9162820458c3fcb536da080a2acdbc7084653334 100644
--- a/src/UnicaenAuth/Service/UserContextFactory.php
+++ b/src/UnicaenAuth/Service/UserContextFactory.php
@@ -19,6 +19,16 @@ class UserContextFactory
         $service = new UserContext();
         $service->setAuthenticationService($authenticationService);
 
+        //
+        // NB: il serait souhaitable d'injecter l'identity provider dans le service UserContext en faisant :
+        //
+        //    $identityProvider = $container->get('BjyAuthorize\Provider\Identity\ProviderInterface');
+        //    $service->setIdentityProvider($identityProvider);
+        //
+        // mais c'est impossible pour l'instant car il y a un cycle dans les dépendances entre services qui
+        // provoque une boucle infinie.
+        //
+
         return $service;
     }
 }
\ No newline at end of file
diff --git a/src/UnicaenAuth/Service/UserMapper.php b/src/UnicaenAuth/Service/UserMapper.php
index 52522ec4a4bbf371fa9311f35f8e5e0a0ac85ef0..efa8c91d75b525b7ad27ef0c039f16337fdcbc17 100644
--- a/src/UnicaenAuth/Service/UserMapper.php
+++ b/src/UnicaenAuth/Service/UserMapper.php
@@ -5,9 +5,10 @@ namespace UnicaenAuth\Service;
 use Doctrine\ORM\EntityManagerInterface;
 use UnicaenAuth\Entity\Db\AbstractUser;
 use UnicaenAuth\Options\ModuleOptions;
-use Zend\Hydrator\HydratorInterface;
+use ZfcUser\Entity\UserInterface as UserEntityInterface;
+use ZfcUser\Mapper\UserInterface;
 
-class UserMapper extends \ZfcUser\Mapper\User
+class UserMapper implements UserInterface
 {
     //========== repris du module zf-commons/zfc-user-doctrine-orm abandonné =========
     /**
@@ -20,12 +21,21 @@ class UserMapper extends \ZfcUser\Mapper\User
      */
     protected $options;
 
+    /**
+     * UserMapper constructor.
+     *
+     * @param EntityManagerInterface $em
+     * @param ModuleOptions          $options
+     */
     public function __construct(EntityManagerInterface $em, ModuleOptions $options)
     {
         $this->em      = $em;
         $this->options = $options;
     }
 
+    /**
+     * {@inheritdoc}
+     */
     public function findByEmail($email)
     {
         $er = $this->em->getRepository($this->options->getUserEntityClass());
@@ -33,6 +43,9 @@ class UserMapper extends \ZfcUser\Mapper\User
         return $er->findOneBy(array('email' => $email));
     }
 
+    /**
+     * {@inheritdoc}
+     */
     public function findByUsername($username)
     {
         $er = $this->em->getRepository($this->options->getUserEntityClass());
@@ -40,6 +53,9 @@ class UserMapper extends \ZfcUser\Mapper\User
         return $er->findOneBy(array('username' => $username));
     }
 
+    /**
+     * {@inheritdoc}
+     */
     public function findById($id)
     {
         $er = $this->em->getRepository($this->options->getUserEntityClass());
@@ -50,7 +66,7 @@ class UserMapper extends \ZfcUser\Mapper\User
     /**
      * {@inheritdoc}
      */
-    public function insert($entity, $tableName = null, HydratorInterface $hydrator = null)
+    public function insert(UserEntityInterface $entity)
     {
         return $this->persist($entity);
     }
@@ -58,12 +74,16 @@ class UserMapper extends \ZfcUser\Mapper\User
     /**
      * {@inheritdoc}
      */
-    public function update($entity, $where = null, $tableName = null, HydratorInterface $hydrator = null)
+    public function update(UserEntityInterface $entity)
     {
         return $this->persist($entity);
     }
 
-    protected function persist($entity)
+    /**
+     * @param UserEntityInterface $entity
+     * @return mixed
+     */
+    protected function persist(UserEntityInterface $entity)
     {
         $this->em->persist($entity);
         $this->em->flush();
diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php
index 2c872f405ff83f11dee28677eab9bfa8afc69fa7..b657ec30526255b8263910eff36108197566e145 100644
--- a/tests/Bootstrap.php
+++ b/tests/Bootstrap.php
@@ -29,7 +29,7 @@ class Bootstrap
 
         static::initAutoloader();
 
-        static::$serviceManager = new ServiceManager(new ServiceManagerConfig());
+        static::$serviceManager = new ServiceManager([]);
     }
 
     public static function getServiceManager()
diff --git a/tests/UnicaenAuthTest/Authentication/Adapter/AbstractFactoryTest.php b/tests/UnicaenAuthTest/Authentication/Adapter/AbstractFactoryTest.php
index 6e4db97b8184012a9c87948da63db69259cb74db..6c0654ababe493e88a58985162670745297c9438 100644
--- a/tests/UnicaenAuthTest/Authentication/Adapter/AbstractFactoryTest.php
+++ b/tests/UnicaenAuthTest/Authentication/Adapter/AbstractFactoryTest.php
@@ -2,11 +2,14 @@
 namespace UnicaenAuthTest\Authentication\Adapter;
 
 use PHPUnit_Framework_TestCase;
+use UnicaenApp\Mapper\Ldap\People;
 use UnicaenAuth\Authentication\Adapter\AbstractFactory;
 use UnicaenAuth\Service\User;
 use Zend\EventManager\EventManager;
 use Zend\EventManager\EventManagerAwareInterface;
 use Zend\ServiceManager\ServiceManager;
+use UnicaenApp\Exception\LogicException;
+use ZfcUser\Options\ModuleOptions;
 
 /**
  * Description of AbstractFactoryTest
@@ -62,7 +65,7 @@ class AbstractFactoryTest extends PHPUnit_Framework_TestCase
 
     /**
      * @dataProvider getInvalidServiceClassName
-     * @expectedException \UnicaenApp\Exception\RuntimeException
+     * @expectedException \UnicaenApp\Exception\LogicException
      * @param string $serviceClassName
      */
     public function testCreateServiceWithNameThrowsExceptionIfInvalidServiceSpecified($serviceClassName)
@@ -85,9 +88,21 @@ class AbstractFactoryTest extends PHPUnit_Framework_TestCase
                            if ('unicaen-auth_user_service' === $serviceName) {
                                return new User();
                            }
-                           if ('event_manager' === $serviceName) {
+                           if ('EventManager' === $serviceName) {
                                return $eventManager;
                            }
+                           if ('zfcuser_module_options' === $serviceName) {
+                               return new ModuleOptions();
+                           }
+                           if ('unicaen-app_module_options' === $serviceName) {
+                               return new \UnicaenApp\Options\ModuleOptions();
+                           }
+                           if ('unicaen-auth_module_options' === $serviceName) {
+                               return new \UnicaenAuth\Options\ModuleOptions();
+                           }
+                           if ('ldap_people_mapper' === $serviceName) {
+                               return new People();
+                           }
                            return null;
                        }));
 
diff --git a/tests/UnicaenAuthTest/Authentication/Adapter/CasTest.php b/tests/UnicaenAuthTest/Authentication/Adapter/CasTest.php
index 82969c0304238c44a89bfbcd1b6cb1d067f2032e..66d9bf2169e5ba50a68cb313a609db07333c5678 100644
--- a/tests/UnicaenAuthTest/Authentication/Adapter/CasTest.php
+++ b/tests/UnicaenAuthTest/Authentication/Adapter/CasTest.php
@@ -5,9 +5,10 @@ namespace UnicaenAuthTest\Authentication\Adapter;
 use PHPUnit_Framework_TestCase;
 use UnicaenApp\Exception\RuntimeException;
 use UnicaenAuth\Authentication\Adapter\Cas;
-use UnicaenAuth\Authentication\Adapter\phpCASWrapper;
 use UnicaenAuth\Options\ModuleOptions;
 use Zend\EventManager\EventManager;
+use Zend\Router\Http\TreeRouteStack;
+use Zend\Uri\Uri;
 use ZfcUser\Authentication\Adapter\AdapterChainEvent;
 use Zend\Authentication\Result;
 
@@ -69,7 +70,7 @@ class CasTest extends PHPUnit_Framework_TestCase
                        }));
 
         $this->adapter = new Cas();
-        $this->adapter->setServiceManager($serviceManager)
+        $this->adapter//->setServiceManager($serviceManager)
                       ->setEventManager(new EventManager());
     }
 
@@ -85,25 +86,28 @@ class CasTest extends PHPUnit_Framework_TestCase
 
     /**
      * @dataProvider getInvalidCasOptions
-     * @expectedException RuntimeException
+     * @expectedException \Exception
+     * @param array $config
      */
-    public function testThrowsExceptionIfNoCasParamSpecified($config)
+    public function testThrowsExceptionIfNoCasParamSpecified(array $config)
     {
         $this->moduleOptions->setCas($config);
+        $this->adapter->setOptions($this->moduleOptions);
         $this->adapter->authenticate(new AdapterChainEvent());
     }
 
     public function testAuthenticateReturnsNullIfNoCasConfigSpecified()
     {
         $this->moduleOptions->setCas([]);
+        $this->adapter->setOptions($this->moduleOptions);
         $result = $this->adapter->authenticate(new AdapterChainEvent());
         $this->assertNull($result);
     }
 
     public function testAuthenticatePopulatesEventWhenAuthenticationSucceeds()
     {
-        /** @var phpCASWrapper|\PHPUnit_Framework_MockObject_MockObject $casClient */
-        $casClient = $this->createMock(phpCASWrapper::class);
+        /** @var \phpCAS|\PHPUnit_Framework_MockObject_MockObject $casClient */
+        $casClient = $this->createMock(\phpCAS::class);
         $casClient->expects($this->once())
                   ->method('getUser')
                   ->will($this->returnValue($username = 'username'));
@@ -112,6 +116,7 @@ class CasTest extends PHPUnit_Framework_TestCase
 
         $event = new AdapterChainEvent();
 
+        $this->adapter->setOptions($this->moduleOptions);
         $this->adapter->authenticate($event);
 
         $this->assertTrue($this->adapter->isSatisfied());
@@ -125,22 +130,36 @@ class CasTest extends PHPUnit_Framework_TestCase
     public function testLogoutReturnsNullIfNoCasConfigSpecified()
     {
         $this->moduleOptions->setCas([]);
+        $this->adapter->setOptions($this->moduleOptions);
         $result = $this->adapter->logout(new AdapterChainEvent());
         $this->assertNull($result);
     }
 
     public function testCanLogoutFromCasWithRedirectService()
     {
-        /** @var phpCASWrapper|\PHPUnit_Framework_MockObject_MockObject $casClient */
-        $casClient = $this->createMock(phpCASWrapper::class);
+        /** @var \phpCAS|\PHPUnit_Framework_MockObject_MockObject $casClient */
+        $casClient = $this->createMock(\phpCAS::class);
         $casClient->expects($this->once())
                   ->method('isAuthenticated')
                   ->will($this->returnValue(true));
         $casClient->expects($this->once())
                   ->method('logoutWithRedirectService');
 
+        /** @var TreeRouteStack|\PHPUnit_Framework_MockObject_MockObject $router */
+        $router = $this->createMock(TreeRouteStack::class);
+        $router
+            ->expects($this->once())
+            ->method('getRequestUri')
+            ->willReturn(new Uri());
+        $router
+            ->expects($this->once())
+            ->method('getBaseUrl')
+            ->willReturn('path');
+
         $this->adapter->setCasClient($casClient);
 
+        $this->adapter->setOptions($this->moduleOptions);
+        $this->adapter->setRouter($router);
         $this->adapter->logout(new AdapterChainEvent());
     }
 }
\ No newline at end of file
diff --git a/tests/UnicaenAuthTest/Authentication/Adapter/DbTest.php b/tests/UnicaenAuthTest/Authentication/Adapter/DbTest.php
index e5edf6c3e0bb8f595d8ac8456941d4f8ef213f3d..e9501903f64ecb95de73b6505983b78db7eee2e9 100644
--- a/tests/UnicaenAuthTest/Authentication/Adapter/DbTest.php
+++ b/tests/UnicaenAuthTest/Authentication/Adapter/DbTest.php
@@ -5,10 +5,13 @@ use PDOException;
 use PHPUnit_Framework_TestCase;
 use UnicaenAuth\Authentication\Adapter\Db;
 use UnicaenAuth\Options\ModuleOptions;
+use Zend\EventManager\EventInterface;
 use Zend\Http\PhpEnvironment\Request;
 use Zend\ServiceManager\Exception\ServiceNotFoundException;
+use Zend\ServiceManager\ServiceManager;
 use Zend\Stdlib\Parameters;
 use ZfcUser\Authentication\Adapter\AdapterChainEvent;
+use ZfcUser\Mapper\User;
 
 /**
  * Description of DbTest
@@ -17,8 +20,16 @@ use ZfcUser\Authentication\Adapter\AdapterChainEvent;
  */
 class DbTest extends PHPUnit_Framework_TestCase
 {
+    /**
+     * @var Db|\PHPUnit_Framework_MockObject_MockObject
+     */
     protected $adapter;
+
     protected $moduleOptions;
+
+    /**
+     * @var User|\PHPUnit_Framework_MockObject_MockObject
+     */
     protected $mapper;
 
     /**
@@ -45,6 +56,7 @@ class DbTest extends PHPUnit_Framework_TestCase
 
         $this->mapper = $mapper = $this->createMock('ZfcUser\Mapper\User'/*, ['findByUsername', 'findByEmail']*/);
 
+        /** @var ServiceManager|\PHPUnit_Framework_MockObject_MockObject $serviceManager */
         $serviceManager = $this->createMock('Zend\ServiceManager\ServiceManager'/*, ['get']*/);
         $serviceManager->expects($this->any())
                        ->method('get')
@@ -68,13 +80,14 @@ class DbTest extends PHPUnit_Framework_TestCase
     public function getException()
     {
         return [
-            [new PDOException()],
+            //[new PDOException()],
             [new ServiceNotFoundException()],
         ];
     }
 
     /**
      * @dataProvider getException
+     * @param \Exception $exception
      */
     public function testAuthenticateReturnsFalseIfExceptionThrown($exception)
     {
@@ -85,8 +98,12 @@ class DbTest extends PHPUnit_Framework_TestCase
         $request = new Request();
         $request->setPost(new Parameters(['identity' => 'bob', 'credential' => "xxxxx"]));
 
-        $event = new AdapterChainEvent();
-        $event->setRequest($request);
+        /** @var EventInterface|\PHPUnit_Framework_MockObject_MockObject $event */
+        $event = $this->createMock(EventInterface::class);
+        $event
+            ->expects($this->exactly(2))
+            ->method('getTarget')
+            ->willReturn((new AdapterChainEvent())->setRequest($request));
 
         $result = $this->adapter->authenticate($event);
         $this->assertFalse($result);
@@ -97,8 +114,12 @@ class DbTest extends PHPUnit_Framework_TestCase
         $request = new Request();
         $request->setPost(new Parameters(['identity' => 'bob', 'credential' => "xxxxx"]));
 
-        $event = new AdapterChainEvent();
-        $event->setRequest($request);
+        /** @var EventInterface|\PHPUnit_Framework_MockObject_MockObject $event */
+        $event = $this->createMock(EventInterface::class);
+        $event
+            ->expects($this->exactly(2))
+            ->method('getTarget')
+            ->willReturn((new AdapterChainEvent())->setRequest($request));
 
         $result = $this->adapter->authenticate($event);
         $this->assertFalse($result);
diff --git a/tests/UnicaenAuthTest/Authentication/Adapter/LdapTest.php b/tests/UnicaenAuthTest/Authentication/Adapter/LdapTest.php
index bf14c6bdf0a98b4642e8953b4ea1afc12ecef9a3..3bbf47bc3d3c4b452b1afffdeaf0604c28b08d4f 100644
--- a/tests/UnicaenAuthTest/Authentication/Adapter/LdapTest.php
+++ b/tests/UnicaenAuthTest/Authentication/Adapter/LdapTest.php
@@ -3,8 +3,11 @@
 namespace UnicaenAuthTest\Authentication\Adapter;
 
 use PHPUnit_Framework_TestCase;
+use UnicaenApp\Mapper\Ldap\People;
 use UnicaenAuth\Authentication\Adapter\Ldap;
 use Zend\Authentication\Result;
+use Zend\Authentication\Storage\StorageInterface;
+use Zend\EventManager\EventInterface;
 use Zend\EventManager\EventManager;
 use Zend\Http\Request;
 use Zend\ServiceManager\ServiceManager;
@@ -19,7 +22,7 @@ use ZfcUser\Authentication\Adapter\AdapterChainEvent;
 class LdapTest extends PHPUnit_Framework_TestCase
 {
     /**
-     * @var Ldap
+     * @var Ldap|\PHPUnit_Framework_MockObject_MockObject
      */
     protected $adapter;
 
@@ -82,12 +85,14 @@ class LdapTest extends PHPUnit_Framework_TestCase
                        }));
 
         $this->adapter = new Ldap();
-        $this->adapter->setServiceManager($serviceManager)
+        $this->adapter//->setServiceManager($serviceManager)
                       ->setEventManager(new EventManager());
     }
 
     public function testCanProvideDefaultLdapAuthAdapter()
     {
+        $this->adapter->setAppModuleOptions($this->appModuleOptions);
+
         $adapter = $this->adapter->getLdapAuthAdapter();
         $this->assertInstanceOf('Zend\Authentication\Adapter\Ldap', $adapter);
 
@@ -99,10 +104,35 @@ class LdapTest extends PHPUnit_Framework_TestCase
 
     public function testAuthenticatingReturnsNullIfAlreadyStatisfied()
     {
-        $event = new AdapterChainEvent();
-        $this->adapter->setSatisfied();
+        /** @var AdapterChainEvent|\PHPUnit_Framework_MockObject_MockObject $adapterChainEvent */
+        $adapterChainEvent = $this->createMock(AdapterChainEvent::class);
+        $adapterChainEvent
+            ->expects($this->once())
+            ->method('setIdentity')
+            ->with('IDENTITY')
+            ->willReturnSelf();
+        $adapterChainEvent
+            ->expects($this->once())
+            ->method('setCode')
+            ->with(Result::SUCCESS)
+            ->willReturnSelf();
+
+        /** @var EventInterface|\PHPUnit_Framework_MockObject_MockObject $event */
+        $event = $this->createMock(EventInterface::class);
+        $event
+            ->expects($this->once())
+            ->method('getTarget')
+            ->willReturn($adapterChainEvent);
+
+        /** @var StorageInterface|\PHPUnit_Framework_MockObject_MockObject $storage */
+        $storage = $this->createMock(StorageInterface::class);
+        $storage
+            ->expects($this->exactly(2))
+            ->method('read')
+            ->willReturn(['is_satisfied' => true, 'identity' => 'IDENTITY']);
+
+        $this->adapter->setStorage($storage);
         $this->assertNull($this->adapter->authenticate($event));
-        $this->assertEquals($event->getCode(), Result::SUCCESS);
     }
 
     public function testUsurpationWithAllowedUsernameAndSuccessfulAuthentication()
@@ -228,7 +258,7 @@ class LdapTest extends PHPUnit_Framework_TestCase
         $this->assertFalse($event->propagationIsStopped());
     }
 
-    protected function _authenticateWithUsurpation($authenticationResultCode, AdapterChainEvent &$event)
+    protected function _authenticateWithUsurpation($authenticationResultCode, AdapterChainEvent &$adapterChainEvent)
     {
         $usernameUsurpateur = 'usurpateur';
         $usernameUsurpe     = 'usurpe';
@@ -246,10 +276,39 @@ class LdapTest extends PHPUnit_Framework_TestCase
                         ->will($this->returnValue(new Result($authenticationResultCode, $usernameUsurpateur)));
         $this->adapter->setLdapAuthAdapter($this->zendAuthLdapAdapter);
 
+        $ldapPeopleMapper = $this->createMock(People::class);
+        $ldapPeopleMapper
+            ->expects($this->once())
+            ->method('findOneByUsername')
+            ->willReturn('not empty');
+
+        $this->adapter->setLdapPeopleMapper($ldapPeopleMapper);
+
         $request = new Request();
         $request->setPost(new Parameters(['identity' => $username, 'credential' => "xxxxx"]));
-        $event->setRequest($request);
+        $adapterChainEvent->setRequest($request);
+
+//        /** @var AdapterChainEvent|\PHPUnit_Framework_MockObject_MockObject $adapterChainEvent */
+//        $adapterChainEvent = $this->createMock(AdapterChainEvent::class);
+//        $adapterChainEvent
+//            ->expects($this->once())
+//            ->method('setIdentity')
+//            ->with('IDENTITY')
+//            ->willReturnSelf();
+//        $adapterChainEvent
+//            ->expects($this->once())
+//            ->method('setCode')
+//            ->with(Result::SUCCESS)
+//            ->willReturnSelf();
+
+        /** @var EventInterface|\PHPUnit_Framework_MockObject_MockObject $event */
+        $event = $this->createMock(EventInterface::class);
+        $event
+            ->expects($this->once())
+            ->method('getTarget')
+            ->willReturn($adapterChainEvent);
 
+        $this->adapter->setOptions($this->authModuleOptions);
         $this->adapter->authenticate($event);
     }
 }
\ No newline at end of file