diff --git a/CHANGELOG.md b/CHANGELOG.md
index fd73fb2da31a2a6dce288a92228bb2961a42a8c9..d2b58cae13ff7cda4eac45ed6cdcddc80cc4cbfb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -40,6 +40,8 @@ Première version officielle sous ZF3.
 
 3.2.0
 -----
+- Configuration de la stratégie d'extraction d'un identifiant utile parmi les données d'authentification shibboleth
+  (config 'shib_user_id_extractor').
 - Possibilité de connaître la source de l'authentification (db, ldap, cas, shib).
 - Possibilité de stopper l'usurpation en cours pour revenir à l'identité d'origine.
 - [FIX] Usurpation d'un compte local en BDD.
diff --git a/config/module.config.php b/config/module.config.php
index fef6e9f1c89d4f0c91e56ff15b0e294771b6fd59..438010a5697f3cd93533db1777c899e099f98b6b 100644
--- a/config/module.config.php
+++ b/config/module.config.php
@@ -187,6 +187,44 @@ $settings = [
             'supannEtuId|supannEmpId',
         ],
         */
+
+        /**
+         * Configuration de la stratégie d'extraction d'un identifiant utile parmi les données d'authentification
+         * shibboleth.
+         * Ex: identifiant de l'usager au sein du référentiel établissement, transmis par l'IDP via le supannRefId.
+         */
+        'shib_user_id_extractor' => [
+            /*
+            // domaine (ex: 'unicaen.fr') de l'EPPN (ex: hochonp@unicaen.fr')
+            'unicaen.fr' => [
+                [
+                    // nom du 1er attribut recherché
+                    'name' => 'supannRefId', // ex: '{OCTOPUS:ID}1234;{ISO15693}044D1AZE7A5P80'
+                    // pattern éventuel pour extraire la partie intéressante
+                    'preg_match_pattern' => '|\{OCTOPUS:ID\}(\d+)|', // ex: permet d'extraire '1234'
+                ],
+                [
+                    // nom du 2e attribut recherché, si le 1er est introuvable
+                    'name' => 'supannEmpId',
+                    // pas de pattern donc valeur brute utilisée
+                    'preg_match_pattern' => null,
+                ],
+                [
+                    // nom du 3e attribut recherché, si le 2e est introuvable
+                    'name' => 'supannEtuId',
+                ],
+            ],
+            */
+            // config de repli pour tous les autres domaines
+            'default' => [
+                [
+                    'name' => 'supannEmpId',
+                ],
+                [
+                    'name' => 'supannEtuId',
+                ],
+            ],
+        ],
     ],
 
     /**
diff --git a/config/unicaen-auth.local.php.dist b/config/unicaen-auth.local.php.dist
index 0633455e8c791eadb78f2f5bea320d207f787c61..1b182e74cd1ef57b1aa4be36331bf8be75f69581 100644
--- a/config/unicaen-auth.local.php.dist
+++ b/config/unicaen-auth.local.php.dist
@@ -115,6 +115,42 @@ return [
             //    'givenName',
             //    'supannEtuId|supannEmpId',
             //],
+
+            /**
+             * Configuration de la stratégie d'extraction d'un identifiant utile parmi les données d'authentification
+             * shibboleth.
+             * Ex: identifiant de l'usager au sein du référentiel établissement, transmis par l'IDP via le supannRefId.
+             */
+            'shib_user_id_extractor' => [
+                // domaine (ex: 'unicaen.fr') de l'EPPN (ex: hochonp@unicaen.fr')
+//                'unicaen.fr' => [
+//                    [
+//                        // nom du 1er attribut recherché
+//                        'name' => 'supannRefId', // ex: '{OCTOPUS:ID}1234;{ISO15693}044D1AZE7A5P80'
+//                        // pattern éventuel pour extraire la partie intéressante
+//                        'preg_match_pattern' => '|\{OCTOPUS:ID\}(\d+)|', // ex: permet d'extraire '1234'
+//                    ],
+//                    [
+//                        // nom du 2e attribut recherché
+//                        'name' => 'supannEmpId',
+//                        // pas de pattern donc valeur brute utilisée
+//                        'preg_match_pattern' => null,
+//                    ],
+//                    [
+//                        // nom du 3e attribut recherché
+//                        'name' => 'supannEtuId',
+//                    ],
+//                ],
+                // config de repli pour tous les autres domaines
+                'default' => [
+                    [
+                        'name' => 'supannEmpId',
+                    ],
+                    [
+                        'name' => 'supannEtuId',
+                    ],
+                ],
+            ],
         ],
 
         /**
diff --git a/src/UnicaenAuth/Authentication/Adapter/LocalAdapterFactory.php b/src/UnicaenAuth/Authentication/Adapter/LocalAdapterFactory.php
index 2733ab3b9bc3797ae141fe31315305f6b7b0b064..04e1866f5926e8727b9b31979e67e6f0056ad270 100644
--- a/src/UnicaenAuth/Authentication/Adapter/LocalAdapterFactory.php
+++ b/src/UnicaenAuth/Authentication/Adapter/LocalAdapterFactory.php
@@ -28,11 +28,11 @@ class LocalAdapterFactory
 
         // db adapter
         if (array_key_exists('db', $localConfig)) {
-            $this->attachSubAdapter($localAdapter, $container, $localConfig['db']);
+            $this->attachSubAdapter($localAdapter, $container, $localConfig['db'], 20); // en 1er
         }
         // ldap adapter
         if (array_key_exists('ldap', $localConfig)) {
-            $this->attachSubAdapter($localAdapter, $container, $localConfig['ldap']);
+            $this->attachSubAdapter($localAdapter, $container, $localConfig['ldap'], 10); // en 2e
         }
 
         return $localAdapter;
@@ -42,8 +42,9 @@ class LocalAdapterFactory
      * @param LocalAdapter $localAdapter
      * @param ContainerInterface $container
      * @param array $config
+     * @param int $priority
      */
-    private function attachSubAdapter(LocalAdapter $localAdapter, ContainerInterface $container, array $config)
+    private function attachSubAdapter(LocalAdapter $localAdapter, ContainerInterface $container, array $config, int $priority)
     {
         $enabled = isset($config['enabled']) && $config['enabled'] === true;
         if (! $enabled) {
@@ -52,7 +53,7 @@ class LocalAdapterFactory
 
         /** @var AbstractAdapter $subAdapter */
         $subAdapter = $container->get($config['adapter']);
-        $subAdapter->attach($localAdapter->getEventManager());
+        $subAdapter->attach($localAdapter->getEventManager(), $priority);
     }
 
 }
\ No newline at end of file
diff --git a/src/UnicaenAuth/Entity/Shibboleth/ShibUser.php b/src/UnicaenAuth/Entity/Shibboleth/ShibUser.php
index 8cba0fd40c89b2ef49a9552523008ea009998fd5..68617a3b1c08c7f0fd2a84a0d40e00a1ac2fa650 100644
--- a/src/UnicaenAuth/Entity/Shibboleth/ShibUser.php
+++ b/src/UnicaenAuth/Entity/Shibboleth/ShibUser.php
@@ -47,6 +47,18 @@ class ShibUser implements UserInterface
      */
     protected $state = 1;
 
+    /**
+     * Retourne la partie domaine DNS de l'EPPN.
+     * Retourne par exemple "unicaen.fr" lorsque l'EPPN est "tartempion@unicaen.fr"
+     *
+     * @return string
+     */
+    public function getEppnDomain()
+    {
+        $parts = explode('@', $this->getEppn());
+
+        return $parts[1];
+    }
 
     /**
      * @return string
diff --git a/src/UnicaenAuth/Service/ShibService.php b/src/UnicaenAuth/Service/ShibService.php
index 27e3519543c4911e682960265c318e6a3f54bd8c..f4cce5a0d66cab3f046a6e840168722d0d8bd366 100644
--- a/src/UnicaenAuth/Service/ShibService.php
+++ b/src/UnicaenAuth/Service/ShibService.php
@@ -19,6 +19,10 @@ use Zend\Session\Container;
  */
 class ShibService
 {
+    const SHIB_USER_ID_EXTRACTOR = 'shib_user_id_extractor';
+
+    const DOMAIN_DEFAULT = 'default';
+
     const KEY_fromShibUser = 'fromShibUser';
     const KEY_toShibUser = 'toShibUser';
 
@@ -105,9 +109,9 @@ EOS;
     private function isAuthenticated(): bool
     {
         return
-            $this->getServerArrayVariable('REMOTE_USER') ||
-            $this->getServerArrayVariable('Shib-Session-ID') ||
-            $this->getServerArrayVariable('HTTP_SHIB_SESSION_ID');
+            $this->getValueFromShibData('REMOTE_USER', $_SERVER) ||
+            $this->getValueFromShibData('Shib-Session-ID', $_SERVER) ||
+            $this->getValueFromShibData('HTTP_SHIB_SESSION_ID', $_SERVER);
     }
 
     /**
@@ -195,6 +199,36 @@ EOS;
         return (array)$this->shibbolethConfig['required_attributes'];
     }
 
+    /**
+     * @return array
+     */
+    private function getShibUserIdExtractorDefaultConfig(): array
+    {
+        return $this->getShibUserIdExtractorConfigForDomain(self::DOMAIN_DEFAULT);
+    }
+
+    /**
+     * Retourne la config permettant d'extraire l'id à partir des attributs.
+     *
+     * @param string $domain
+     * @return array
+     */
+    private function getShibUserIdExtractorConfigForDomain(string $domain): array
+    {
+        $key = self::SHIB_USER_ID_EXTRACTOR;
+        if (! array_key_exists($key, $this->shibbolethConfig)) {
+            throw new RuntimeException("Aucune config '$key' trouvée.");
+        }
+
+        $config = $this->shibbolethConfig[$key];
+
+        if (! array_key_exists($domain, $config)) {
+            return [];
+        }
+
+        return $config[$domain];
+    }
+
     /**
      *
      */
@@ -224,7 +258,6 @@ EOS;
         $this->assertRequiredAttributesExistInData($data);
 
         $eppn = $this->getValueFromShibData('eppn', $data);
-        $supannId = $this->getValueFromShibData('supannEmpId', $data) ?: $this->getValueFromShibData('supannEtuId', $data);
         $email = $this->getValueFromShibData('mail', $data);
         $displayName = $this->getValueFromShibData('displayName', $data);
         $givenName = $this->getValueFromShibData('givenName', $data);
@@ -234,17 +267,22 @@ EOS;
         Assertion::contains($eppn, '@', "L'eppn '" . $eppn . "' n'est pas de la forme 'id@domaine' attendue (ex: 'tartempion@unicaen.fr')");
 
         $shibUser = new ShibUser();
+        // propriétés de UserInterface
         $shibUser->setEppn($eppn);
-        $shibUser->setId($supannId);
+        $shibUser->setUsername($eppn);
+        $domain = $shibUser->getEppnDomain(); // possible uniquement après $shibUser->setEppn($eppn)
+        $id = $this->extractShibUserIdValueForDomainFromShibData($domain, $data);
+        $shibUser->setId($id);
         $shibUser->setDisplayName($displayName);
         $shibUser->setEmail($email);
+        // autres propriétés
         $shibUser->setNom($surname);
         $shibUser->setPrenom($givenName);
         $shibUser->setCivilite($civilite);
 
         return $shibUser;
     }
-    
+
     /**
      * Retourne true si les données stockées en session indiquent qu'une usurpation d'identité Shibboleth est en cours.
      *
@@ -332,7 +370,7 @@ EOS;
             throw new RuntimeException("Anomalie: clé '$key' introuvable");
         }
 
-        $this->simulateAuthenticatedUser($toShibUser, 'supannEmpId');
+        $this->simulateAuthenticatedUser($toShibUser);
 
         return $this;
     }
@@ -394,26 +432,15 @@ EOS;
      * qui se serait authentifié via Shibboleth.
      *
      * @param ShibUser $shibUser Utilisateur dont on veut usurper l'identité.
-     * @param string $keyForId Clé du tableau $_SERVER dans laquelle mettre l'id de l'utilsateur spécifié.
-     *                         Ex: 'supannEmpId', 'supannEtuId'.
      */
-    public function simulateAuthenticatedUser(ShibUser $shibUser, $keyForId = 'supannEmpId')
+    public function simulateAuthenticatedUser(ShibUser $shibUser)
     {
         // 'REMOTE_USER' (notamment) est utilisé pour savoir si un utilisateur est authentifié ou non
         $this->setServerArrayVariable('REMOTE_USER', $shibUser->getEppn());
 
-//        // on s'assure que tous les attributs obligatoires ont une valeur
-//        foreach ($this->getShibbolethRequiredAttributes() as $requiredAttribute) {
-//            // un pipe permet d'exprimer un OU logique, ex: 'supannEmpId|supannEtuId'
-//            $attributes = array_map('trim', explode('|', $requiredAttribute));
-//            foreach ($attributes as $attribute) {
-//                $this->setServerArrayVariable($attribute, 'qqchose');
-//            }
-//        }
-
         // pour certains attributs, on veut une valeur sensée!
         $this->setServerArrayVariable('eppn', $shibUser->getEppn());
-        $this->setServerArrayVariable($keyForId, $shibUser->getId());
+        $this->setServerArrayVariable('supannEmpId', $shibUser->getId()); // ou bien 'supannEtuId', peu importe.
         $this->setServerArrayVariable('displayName', $shibUser->getDisplayName());
         $this->setServerArrayVariable('mail', $shibUser->getEppn());
         $this->setServerArrayVariable('sn', $shibUser->getNom());
@@ -432,18 +459,20 @@ EOS;
             throw new RuntimeException('Des attributs Shibboleth obligatoires font défaut dans $_SERVER.', null, $e);
         }
 
-        $eppn = $this->getServerArrayVariable('eppn');
-        $id = $this->getServerArrayVariable('supannEtuId') ?: $this->getServerArrayVariable('supannEmpId');
-        $mail = $this->getServerArrayVariable('mail');
-        $displayName = $this->getServerArrayVariable('displayName');
-        $surname = $this->getServerArrayVariable('sn') ?: $this->getServerArrayVariable('surname');
-        $givenName = $this->getServerArrayVariable('givenName');
-        $civilite = $this->getServerArrayVariable('supannCivilite');
+        $eppn = $this->getValueFromShibData('eppn', $_SERVER);
+        $mail = $this->getValueFromShibData('mail', $_SERVER);
+        $displayName = $this->getValueFromShibData('displayName', $_SERVER);
+        $surname = $this->getValueFromShibData('sn', $_SERVER) ?: $this->getValueFromShibData('surname', $_SERVER);
+        $givenName = $this->getValueFromShibData('givenName', $_SERVER);
+        $civilite = $this->getValueFromShibData('supannCivilite', $_SERVER);
 
         $shibUser = new ShibUser();
         // propriétés de UserInterface
-        $shibUser->setId($id);
+        $shibUser->setEppn($eppn);
         $shibUser->setUsername($eppn);
+        $domain = $shibUser->getEppnDomain(); // possible uniquement après $shibUser->setEppn($eppn)
+        $id = $this->extractShibUserIdValueForDomainFromShibData($domain, $_SERVER);
+        $shibUser->setId($id);
         $shibUser->setDisplayName($displayName);
         $shibUser->setEmail($mail);
         $shibUser->setPassword(null);
@@ -455,6 +484,40 @@ EOS;
         return $shibUser;
     }
 
+    /**
+     * @param string $domain
+     * @param array $data
+     * @return string|null
+     */
+    private function extractShibUserIdValueForDomainFromShibData(string $domain, array $data): ?string
+    {
+        $config = $this->getShibUserIdExtractorConfigForDomain($domain);
+        if (empty($config)) {
+            $config = $this->getShibUserIdExtractorDefaultConfig();
+            if (empty($config)) {
+                throw new RuntimeException("Aucune config trouvée ni pour le domaine '$domain' ni par défaut.");
+            }
+        }
+
+        foreach ($config as $array) {
+            $name = $array['name'];
+            $value = $this->getValueFromShibData($name, $data);
+            if ($value !== null) {
+                $pregMatchPattern = $array['preg_match_pattern'] ?? null;
+                if ($pregMatchPattern !== null) {
+                    if (preg_match($pregMatchPattern, $value, $matches) === 0) {
+                        throw new RuntimeException("Le pattern '$pregMatchPattern' n'a pas permis d'extraire une valeur de '$name'.");
+                    }
+                    $value = $matches[1];
+                }
+
+                return $value;
+            }
+        }
+
+        return null;
+    }
+
     /**
      * Retourne l'URL de déconnexion Shibboleth.
      *
@@ -554,19 +617,4 @@ EOS;
 
         $_SERVER[$key] = $value;
     }
-
-    /**
-     * @param $name
-     * @return string|null
-     */
-    private function getServerArrayVariable($name): ?string
-    {
-        $key = $this->getShibbolethAliasFor($name) ?: $name;
-
-        if (! array_key_exists($key, $_SERVER)) {
-            return null;
-        }
-
-        return $_SERVER[$key];
-    }
 }
\ No newline at end of file