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/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;
+    }
+}