diff --git a/config/module.config.php b/config/module.config.php index 0bad6991bf0183bf6c54711b74309f4f1af448a6..b6144118d697fc96b5dc1b80767fa5748d150e4a 100644 --- a/config/module.config.php +++ b/config/module.config.php @@ -5,6 +5,7 @@ use UnicaenAuth\Service\ShibService; use UnicaenAuth\Service\ShibServiceFactory; use UnicaenAuth\Service\UserContextFactory; use UnicaenAuth\View\Helper\ShibConnectViewHelperFactory; +use UnicaenAuth\View\Helper\UserUsurpationHelperFactory; $settings = [ /** @@ -122,7 +123,6 @@ return [ ['controller' => 'UnicaenApp\Controller\Application', 'action' => 'informatique-et-libertes', 'roles' => []], ['controller' => 'UnicaenApp\Controller\Application', 'action' => 'refresh-session', 'roles' => []], ['controller' => 'UnicaenAuth\Controller\Utilisateur', 'action' => 'selectionner-profil', 'roles' => []], - ['controller' => 'UnicaenAuth\Controller\Utilisateur', 'action' => 'usurper-identite', 'roles' => []], ['controller' => 'UnicaenAuth\Controller\Auth', 'action' => 'shibboleth', 'roles' => []], ], @@ -433,6 +433,7 @@ return [ 'userInfo' => 'UnicaenAuth\View\Helper\UserInfoFactory', 'userProfileSelect' => 'UnicaenAuth\View\Helper\UserProfileSelectFactory', 'userProfileSelectRadioItem' => 'UnicaenAuth\View\Helper\UserProfileSelectRadioItemFactory', + 'userUsurpation' => UserUsurpationHelperFactory::class, 'shibConnect' => ShibConnectViewHelperFactory::class, ], 'invokables' => [ diff --git a/src/UnicaenAuth/Authentication/Storage/Shib.php b/src/UnicaenAuth/Authentication/Storage/Shib.php index 1bc25efa09bfdb760746b6a8e63aa2ec2fad23d1..2e9600d7b0b3303a1fd34ed1a8c993b6ef16c621 100644 --- a/src/UnicaenAuth/Authentication/Storage/Shib.php +++ b/src/UnicaenAuth/Authentication/Storage/Shib.php @@ -51,15 +51,57 @@ class Shib implements ChainableStorage, ServiceLocatorAwareInterface */ public function read(ChainEvent $e) { - /** @var ShibService $shib */ - $shib = $this->getServiceLocator()->get(ShibService::class); - $shibUser = $shib->getAuthenticatedUser(); + $shibUser = $this->getAuthenticatedUser(); $e->addContents('shib', $shibUser); return $shibUser; } + /** + * @return null|ShibUser + */ + private function getAuthenticatedUser() + { + if (! $this->isShibbolethEnabled()) { + return null; + } + + if (null !== $this->resolvedIdentity) { + return $this->resolvedIdentity; + } + + /** @var ShibService $shib */ + $shib = $this->getServiceLocator()->get(ShibService::class); + + $this->resolvedIdentity = $shib->getAuthenticatedUser(); + + return $this->resolvedIdentity; + } + + /** + * @return bool + */ + private function isShibbolethEnabled() + { + $options = $this->getModuleOptions(); + $shibboleth = $options->getShibboleth(); + + return isset($shibboleth['enable']) && (bool) $shibboleth['enable']; + } + + /** + * @return ModuleOptions + */ + private function getModuleOptions() + { + if (null === $this->options) { + $this->options = $this->getServiceLocator()->get('unicaen-auth_module_options'); + } + + return $this->options; + } + /** * Writes $contents to storage * diff --git a/src/UnicaenAuth/Controller/AuthController.php b/src/UnicaenAuth/Controller/AuthController.php index 0bec8234c32653ee12f23b86a2e74547828658be..51fc785de01762fca73aa092b0aab8ce412a9585 100644 --- a/src/UnicaenAuth/Controller/AuthController.php +++ b/src/UnicaenAuth/Controller/AuthController.php @@ -3,6 +3,7 @@ namespace UnicaenAuth\Controller; use UnicaenApp\Exception\RuntimeException; +use UnicaenAuth\Service\ShibService; use UnicaenAuth\Service\Traits\ShibServiceAwareTrait; use UnicaenAuth\Service\Traits\UserServiceAwareTrait; use Zend\Authentication\AuthenticationService; @@ -23,6 +24,16 @@ class AuthController extends AbstractActionController use UserServiceAwareTrait; /** + * Cette action n'est exécutée qu'une fois l'authentification Shibboleth réalisée avec succès. + * + * Lorsque l'authentification Shibboleth est activée (unicaen-auth.shibboleth.enable === true), + * et que la config Apache est correcte, une requête à l'adresse correspondant à cette action + * (suite au clic sur le bouton "Authentification Shibboleth, typiquement) + * est détournée pour réaliser l'authentification. + * Ce n'est qu'une fois l'authentification réalisée avec succès que cette action entre en jeu. + * + * @see ShibService::apacheConfigSnippet() + * * @return Response|array */ public function shibbolethAction() @@ -36,9 +47,14 @@ class AuthController extends AbstractActionController $this->zfcUserAuthentication()->getAuthService()->clearIdentity(); // déconnexion Shibboleth le cas échéant - if ($this->shibService->isShibbolethEnable()) { + if ($this->shibService->isShibbolethEnabled()) { + // désactivation de l'usurpation d'identité éventuelle + $this->shibService->deactivateUsurpation(); + + // URL par défaut vers laquelle on redirige après déconnexion : accueil $homeUrl = $this->url()->fromRoute('home', [], ['force_canonical' => true]); $returnAbsoluteUrl = $this->params()->fromQuery('return', $homeUrl); + return $this->redirect()->toUrl($this->shibService->getLogoutUrl($returnAbsoluteUrl)); } else { return []; // une page d'aide s'affichera @@ -65,9 +81,4 @@ class AuthController extends AbstractActionController return $this->redirect()->toUrl($redirectUrl); } - - public function shibboleth() - { - - } } \ No newline at end of file diff --git a/src/UnicaenAuth/Controller/UtilisateurController.php b/src/UnicaenAuth/Controller/UtilisateurController.php index 707cbae58285b9e207e2122e89de398ad9249c84..fbb9fc50018c26e0dcbfee1b1c16aa22b20ea837 100644 --- a/src/UnicaenAuth/Controller/UtilisateurController.php +++ b/src/UnicaenAuth/Controller/UtilisateurController.php @@ -2,78 +2,14 @@ namespace UnicaenAuth\Controller; -use UnicaenAuth\Entity\Db\UserInterface; -use UnicaenAuth\Entity\Ldap\People; -use UnicaenAuth\Entity\Shibboleth\ShibUser; -use UnicaenAuth\Options\ModuleOptions; -use Zend\Authentication\AuthenticationService; use Zend\Http\Request; -use Zend\Http\Response; use Zend\Mvc\Controller\AbstractActionController; /** - * - * * @author Bertrand GAUTHIER <bertrand.gauthier at unicaen.fr> */ class UtilisateurController extends AbstractActionController { - /** - * Usurpe l'identité d'un autre utilisateur. - * - * @return Response - */ - public function usurperIdentiteAction() - { - $request = $this->getRequest(); - if (! $request instanceof Request) { - exit(1); - } - - $redirection = $this->redirect()->toRoute('home'); - - $newIdentity = $request->getQuery('identity', $request->getPost('identity')); - if (! $newIdentity) { - return $redirection; - } - - /** @var AuthenticationService $authenticationService */ - $authenticationService = $this->getServiceLocator()->get(AuthenticationService::class); - - /** @var ModuleOptions $options */ - $options = $this->getServiceLocator()->get('unicaen-auth_module_options'); - - $currentIdentity = $authenticationService->getIdentity(); - if (! $currentIdentity) { - return $redirection; - } - if (! is_array($currentIdentity)) { - return $redirection; - } - - if (isset($currentIdentity['shib'])) { - /** @var ShibUser $currentIdentity */ - $currentIdentity = $currentIdentity['shib']; - } elseif (isset($currentIdentity['ldap'])) { - /** @var People $currentIdentity */ - $currentIdentity = $currentIdentity['ldap']; - } elseif (isset($currentIdentity['db'])) { - /** @var UserInterface $currentIdentity */ - $currentIdentity = $currentIdentity['db']; - } else { - return $redirection; - } - - $currentIdentity = $currentIdentity->getUsername(); - if (! in_array($currentIdentity, $options->getUsurpationAllowedUsernames())) { - return $redirection; - } - - $authenticationService->getStorage()->write($newIdentity); - - return $redirection; - } - /** * 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. diff --git a/src/UnicaenAuth/Entity/Shibboleth/ShibUser.php b/src/UnicaenAuth/Entity/Shibboleth/ShibUser.php index b0c785c2534ceb782d6c79b8b1285a02a7973bfb..3312082344781febd0e56333e80c4a2aaf829613 100644 --- a/src/UnicaenAuth/Entity/Shibboleth/ShibUser.php +++ b/src/UnicaenAuth/Entity/Shibboleth/ShibUser.php @@ -55,6 +55,16 @@ class ShibUser implements UserInterface return $this->getUsername(); } + /** + * Set eduPersoPrincipalName (EPPN). + * + * @param string $eppn eduPersoPrincipalName (EPPN), ex: 'gauthierb@unicaen.fr' + */ + public function setEppn($eppn) + { + $this->setUsername($eppn); + } + /** * Get id. * diff --git a/src/UnicaenAuth/Service/ShibService.php b/src/UnicaenAuth/Service/ShibService.php index d473dbf667ae405835a9320d2a6f37715d50277a..45cdd52de3fba4187dffdcc5cc07b22ac27af073 100644 --- a/src/UnicaenAuth/Service/ShibService.php +++ b/src/UnicaenAuth/Service/ShibService.php @@ -2,10 +2,14 @@ namespace UnicaenAuth\Service; +use Assert\Assertion; +use Assert\AssertionFailedException; +use UnicaenApp\Exception\LogicException; use UnicaenApp\Exception\RuntimeException; use UnicaenAuth\Entity\Shibboleth\ShibUser; use UnicaenAuth\Options\ModuleOptions; use Zend\Mvc\Router\Http\TreeRouteStack; +use Zend\Session\Container; /** * Shibboleth service @@ -44,10 +48,47 @@ EOS; return $text; } + /** + * @return ShibUser|null + */ + public function getAuthenticatedUser() + { + if (! $this->isShibbolethEnabled()) { + return null; + } + + if ($this->authenticatedUser === null) { + if (! $this->getShibbolethSimulate() && ! isset($_SERVER['REMOTE_USER'])) { + try { + Assertion::keyIsset($_SERVER, 'REMOTE_USER'); + } catch (AssertionFailedException $e) { + throw new RuntimeException("La clé suivante est introuvable ou sans valeur dans \$_SERVER : 'REMOTE_USER'."); + } + } + + // gestion de l'usurpation éventuelle + if ($this->isUsurpationActive()) { + $this->handleUsurpation(); + } + + if (empty($_SERVER['REMOTE_USER'])) { + if ($this->isSimulationActive()) { + $this->handleSimulation(); + } else { + return null; + } + } + + $this->authenticatedUser = $this->createShibUserFromServerArrayData(); + } + + return $this->authenticatedUser; + } + /** * @return boolean */ - public function isShibbolethEnable() + public function isShibbolethEnabled() { $options = $this->options->getShibboleth(); @@ -55,24 +96,160 @@ EOS; } /** - * @return ShibUser|null + * @return array */ - public function getAuthenticatedUser() + public function getShibbolethSimulate() { - if ($this->authenticatedUser === null) { - if (empty($_SERVER['REMOTE_USER'])) { - return null; - } - $this->authenticatedUser = $this->createShibUser(); + $options = $this->options->getShibboleth(); + + if (! array_key_exists('simulate', $options) || ! is_array($options['simulate'])) { + return []; } - return $this->authenticatedUser; + return $options['simulate']; + } + + /** + * Retourne true si la simulation d'un utilisateur authentifié via Shibboleth est en cours. + * + * @return bool + */ + private function isSimulationActive() + { + $options = $this->options->getShibboleth(); + + if (array_key_exists('simulate', $options) && is_array($options['simulate']) && ! empty($options['simulate'])) { + return true; + } + + return false; + } + + /** + * @return $this + */ + private function handleSimulation() + { + $simulate = $this->getShibbolethSimulate(); + + try { + Assertion::keyIsset($simulate, 'eppn', + "Clé 'eppn' introuvable ou sans valeur dans l'option 'unicaen-auth.shibboleth.simulate'"); + Assertion::eq(count(array_intersect($keys = ['supannEmpId', 'supannEtuId'], array_keys($simulate))), 1, + "L'une ou l'autre de ces clés doit être présente dans l'option 'unicaen-auth.shibboleth.simulate': " . + implode(', ', $keys)); + } catch (AssertionFailedException $e) { + throw new LogicException("Configuration erronée", null, $e); + } + + $eppn = $simulate['eppn']; + $supannId = $simulate['supannEmpId'] ?: $simulate['supannEtuId']; + $email = isset($simulate['email']) ? $simulate['email'] : null; + + $shibUser = new ShibUser(); + $shibUser->setEppn($eppn); + $shibUser->setId($supannId); + $shibUser->setDisplayName("$eppn ($supannId)"); + $shibUser->setEmail($email); + $shibUser->setNom('Shibboleth'); + $shibUser->setPrenom('Simulation'); + + ShibService::simulateAuthenticatedUser($shibUser); + + return $this; + } + + /** + * Retourne true si les données stockées en session indiquent qu'une usurpation d'identité Shibboleth est en cours. + * + * @return bool + */ + private function isUsurpationActive() + { + return $this->getSessionContainer()->offsetExists('fromShibUser'); + } + + /** + * @param ShibUser $fromShibUser + * @param ShibUser $toShibUser + * @return self + */ + public function activateUsurpation(ShibUser $fromShibUser, ShibUser $toShibUser) + { + // le login doit faire partie des usurpateurs autorisés + if (! in_array($fromShibUser->getUsername(), $this->options->getUsurpationAllowedUsernames())) { + throw new RuntimeException("Usurpation non autorisée"); + } + + $session = $this->getSessionContainer(); + $session->offsetSet('fromShibUser', $fromShibUser); + $session->offsetSet('toShibUser', $toShibUser); + + return $this; + } + + /** + * Suppression des données stockées en session concernant l'usurpation d'identité Shibboleth. + * + * @return self + */ + public function deactivateUsurpation() + { + $session = $this->getSessionContainer(); + $session->offsetUnset('fromShibUser'); + $session->offsetUnset('toShibUser'); + + return $this; + } + + /** + * @return $this + */ + private function handleUsurpation() + { + $session = $this->getSessionContainer(); + + /** @var ShibUser|null $toShibUser */ + $toShibUser = $session->offsetGet('toShibUser'); + if ($toShibUser === null) { + throw new RuntimeException("Anomalie: 'toShibUser' introuvable"); + } + + static::simulateAuthenticatedUser($toShibUser, 'supannEmpId'); + + return $this; + } + + /** + * @return Container + */ + private function getSessionContainer() + { + return new Container(ShibService::class); + } + + /** + * Inscrit dans le tableau $_SERVER le nécessaire pour usurper l'identité d'un utilisateur + * qui ce 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 static function simulateAuthenticatedUser(ShibUser $shibUser, $keyForId = 'supannEmpId') + { + $_SERVER['REMOTE_USER'] = $shibUser->getEppn(); + $_SERVER[$keyForId] = $shibUser->getId(); + $_SERVER['displayName'] = $shibUser->getDisplayName(); + $_SERVER['mail'] = $shibUser->getEmail(); + $_SERVER['sn'] = $shibUser->getNom(); + $_SERVER['givenName'] = $shibUser->getPrenom(); } /** * @return ShibUser */ - private function createShibUser() + private function createShibUserFromServerArrayData() { $eppn = $_SERVER['REMOTE_USER']; @@ -81,7 +258,7 @@ EOS; } elseif (isset($_SERVER['supannEmpId'])) { $id = $_SERVER['supannEmpId']; } else { - throw new RuntimeException('Un au moins des attributs suivants doit exister dans $_SERVER : supannEtuId, supannEmpId.'); + throw new RuntimeException('Un au moins des attributs Shibboleth suivants doit exister dans $_SERVER : supannEtuId, supannEmpId.'); } $mail = null; @@ -134,6 +311,10 @@ EOS; */ public function getLogoutUrl($returnAbsoluteUrl = null) { + if ($this->getShibbolethSimulate()) { + return '/'; + } + $logoutRelativeUrl = '/Shibboleth.sso/Logout?return='; // NB: '?return=' semble obligatoire! if ($returnAbsoluteUrl) { diff --git a/src/UnicaenAuth/Service/UserContext.php b/src/UnicaenAuth/Service/UserContext.php index 65aab76944b4043dc4f522d14d2acb782f6a35ca..0fc768d899a4205cd2e15582f902ff1985e40a60 100644 --- a/src/UnicaenAuth/Service/UserContext.php +++ b/src/UnicaenAuth/Service/UserContext.php @@ -5,6 +5,7 @@ namespace UnicaenAuth\Service; use BjyAuthorize\Acl\Role; use UnicaenApp\Exception\RuntimeException; use UnicaenApp\Traits\SessionContainerTrait; +use UnicaenAuth\Entity\Shibboleth\ShibUser; use UnicaenAuth\Event\UserRoleSelectedEvent; use UnicaenAuth\Provider\Identity\Chain; use Zend\EventManager\EventManagerAwareInterface; @@ -73,6 +74,24 @@ class UserContext extends AbstractService implements EventManagerAwareInterface + /** + * Retourne l'éventuel utilisateur Shibboleth courant. + * + * @return ShibUser|null + */ + public function getShibUser() + { + if (($identity = $this->getIdentity())) { + if (isset($identity['shib']) && $identity['shib'] instanceof ShibUser) { + return $identity['shib']; + } + } + + return null; + } + + + /** * Retourne les données d'identité correspondant à l'utilisateur courant. * @@ -91,6 +110,27 @@ class UserContext extends AbstractService implements EventManagerAwareInterface } + /** + * Retourne l'identifiant de connexion de l'utilisateur courant. + * + * @return string|null + */ + public function getIdentityUsername() + { + if ($user = $this->getShibUser()) { + return $user->getUsername(); + } + if ($user = $this->getLdapUser()) { + return $user->getUsername(); + } + if ($user = $this->getDbUser()) { + return $user->getUsername(); + } + + return null; + } + + /** * @param string $roleId diff --git a/src/UnicaenAuth/View/Helper/ShibConnectViewHelper.php b/src/UnicaenAuth/View/Helper/ShibConnectViewHelper.php index 2038e8f7d86fc3d34ec46f410663bf1e508b83eb..477ddf603ee7843c61482db6866c86fcda1fa64c 100644 --- a/src/UnicaenAuth/View/Helper/ShibConnectViewHelper.php +++ b/src/UnicaenAuth/View/Helper/ShibConnectViewHelper.php @@ -34,7 +34,7 @@ class ShibConnectViewHelper extends AbstractHelper */ private function render() { - if (! $this->shibService->isShibbolethEnable()) { + if (! $this->shibService->isShibbolethEnabled()) { return ''; } diff --git a/src/UnicaenAuth/View/Helper/UserInfo.php b/src/UnicaenAuth/View/Helper/UserInfo.php index 83f28bd82b0acb6ff44708e632ac4453cde371b6..c837447870cf2e20557daf2ea1c11088abdbf09d 100644 --- a/src/UnicaenAuth/View/Helper/UserInfo.php +++ b/src/UnicaenAuth/View/Helper/UserInfo.php @@ -102,7 +102,11 @@ class UserInfo extends UserAbstract } $out .= $aucuneAffDispo; } - + + // formulaire d'usurpation d'identité + $userUsurpationHelper = $this->view->plugin('userUsurpation'); /* @var $userUsurpationHelper \UnicaenAuth\View\Helper\UserUsurpationHelper */ + $out .= $userUsurpationHelper(); + return $out; } diff --git a/src/UnicaenAuth/View/Helper/UserUsurpationHelper.php b/src/UnicaenAuth/View/Helper/UserUsurpationHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..ab6d807fa7e95497c562f587ecdcaaf516be401a --- /dev/null +++ b/src/UnicaenAuth/View/Helper/UserUsurpationHelper.php @@ -0,0 +1,141 @@ +<?php + +namespace UnicaenAuth\View\Helper; + +use UnicaenApp\Form\View\Helper\FormControlGroup; +use UnicaenAuth\Options\ModuleOptions; +use Zend\Form\Element\Submit; +use Zend\Form\Element\Text; +use Zend\Form\Form; +use Zend\Form\View\Helper\Form as FormHelper; +use Zend\View\Renderer\PhpRenderer; + +/** + * Aide de vue permettant de saisir et valider le login de l'utilisateur dont on veut usurper l'identité. + * + * @author Bertrand GAUTHIER <bertrand.gauthier@unicaen.fr> + */ +class UserUsurpationHelper extends UserAbstract +{ + /** + * @var PhpRenderer + */ + protected $view; + + /** + * @var ModuleOptions + */ + protected $moduleOptions; + + /** + * @var string + */ + private $url; + + /** + * @var bool + */ + private $usurpationEnabled = false; + + /** + * Point d'entrée. + * + * @return self + */ + public function __invoke() + { + return $this; + } + + /** + * Retourne le code HTML généré par cette aide de vue. + * + * @return string + */ + public function __toString() + { + if (! $this->usurpationEnabled) { + return ''; + } + + /** @var FormHelper $formHelper */ + $formHelper = $this->view->plugin('form'); + /** @var FormControlGroup $formControlGroupHelper */ + $formControlGroupHelper = $this->view->plugin('formControlGroup'); + + $form = new Form('user-usurpation-form'); + $form->setAttributes([ + 'class' => 'user-usurpation-form', + 'action' => $this->url, + ]); + + $input = new Text('identity'); + $input->setAttributes([ + 'id' => 'user-usurpation-input', + 'placeholder' => "Identifiant utilisateur", + ]); + + $submit = new Submit('submit'); + $submit->setValue("Usurper"); + $submit->setAttributes([ + 'class' => 'user-usurpation-submit btn btn-info', + ]); + + $html = ''; + $html .= $formHelper->openTag($form); + $html .= "<div><strong>Usurpation d'identité :</strong></div>"; + $html .= $formControlGroupHelper->__invoke($input); + $html .= $formControlGroupHelper->__invoke($submit); + $html .= $formHelper->closeTag(); + + $html .= <<<EOS +<script> + $(".user-usurpation-form").submit(function() { + $("body *").css('cursor', 'wait'); + }); + var input = $("#user-usurpation-input").on('input', function() { + updateUsurpationSubmit(); + }); + function updateUsurpationSubmit() { + $(".user-usurpation-submit").prop("disabled", input.val().length === 0); + } + updateUsurpationSubmit(); +</script> +EOS; + + return $html; + } + + /** + * @param string $url + * @return $this + */ + public function setUrl($url) + { + $this->url = $url; + + return $this; + } + + /** + * @param ModuleOptions $moduleOptions + * @return self + */ + public function setModuleOptions(ModuleOptions $moduleOptions) + { + $this->moduleOptions = $moduleOptions; + + return $this; + } + + /** + * @param bool $usurpationEnabled + * @return self + */ + public function setUsurpationEnabled($usurpationEnabled = true) + { + $this->usurpationEnabled = $usurpationEnabled; + + return $this; + } +} \ No newline at end of file diff --git a/src/UnicaenAuth/View/Helper/UserUsurpationHelperFactory.php b/src/UnicaenAuth/View/Helper/UserUsurpationHelperFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..9aa21103a2f05a72c3d26c2587b9c97e9123de5d --- /dev/null +++ b/src/UnicaenAuth/View/Helper/UserUsurpationHelperFactory.php @@ -0,0 +1,38 @@ +<?php + +namespace UnicaenAuth\View\Helper; + +use UnicaenAuth\Options\ModuleOptions; +use UnicaenAuth\Service\UserContext; +use Zend\View\Helper\Url; +use Zend\View\HelperPluginManager; + +class UserUsurpationHelperFactory +{ + /** + * @param HelperPluginManager $hpm + * @return UserUsurpationHelper + */ + public function __invoke(HelperPluginManager $hpm) + { + /** @var Url $urlHelper */ + $urlHelper = $hpm->get('url'); + $url = $urlHelper->__invoke('utilisateur/default', ['action' => 'usurper-identite']); + + /** @var UserContext $userContextService */ + $userContextService = $hpm->getServiceLocator()->get('authUserContext'); + + /** @var ModuleOptions $moduleOptions */ + $moduleOptions = $hpm->getServiceLocator()->get('unicaen-auth_module_options'); + + $usurpationAllowed = in_array( + $userContextService->getIdentityUsername(), + $moduleOptions->getUsurpationAllowedUsernames()); + + $helper = new UserUsurpationHelper($userContextService); + $helper->setUrl($url); + $helper->setUsurpationEnabled($usurpationAllowed); + + return $helper; + } +} \ No newline at end of file