*/ class Cas extends AbstractAdapter { use ModuleOptionsAwareTrait; const TYPE = 'cas'; /** * @var string */ protected $type = self::TYPE; /** * @var array */ protected $casOptions; /** * @var phpCAS */ protected $casClient; /** * @var LdapPeopleMapper */ protected $ldapPeopleMapper; /** * @var User */ private $userService; /** * @param User $userService */ public function setUserService(User $userService) { $this->userService = $userService; } /** * @var RouteInterface */ private $router; /** * @param RouteInterface $router */ public function setRouter(RouteInterface $router) { $this->router = $router; } /** * @inheritDoc */ public function authenticate(EventInterface $e): bool { // NB: Dans la version 3.0.0 de zf-commons/zfc-user, cette méthode prend un EventInterface. // Mais dans la branche 3.x, c'est un AdapterChainEvent ! // Si un jour c'est un AdapterChainEvent qui est attendu, plus besoin de faire $e->getTarget(). $event = $e->getTarget(); /* @var $event AdapterChainEvent */ $type = $event->getRequest()->getPost()->get('type'); if ($type !== $this->type) { return false; } // if ($e->getIdentity()) { // return; // } /* DS : modification liée à une boucle infinie lors de l'authentification CAS */ if ($this->isSatisfied()) { $storage = $this->getStorage()->read(); $event ->setIdentity($storage['identity']) ->setCode(AuthenticationResult::SUCCESS) ->setMessages(['Authentication successful.']); return true; } error_reporting($oldErrorReporting = error_reporting() & ~E_NOTICE); $this->getCasClient()->forceAuthentication(); // at this step, the user has been authenticated by the CAS server // and the user's login name can be read with phpCAS::getUser(). $identity = $this->createSessionIdentity($this->getCasClient(false)->getUser()); error_reporting($oldErrorReporting); $event->setIdentity($identity); $this->setSatisfied(true); $storage = $this->getStorage()->read(); $storage['identity'] = $event->getIdentity(); $this->getStorage()->write($storage); $event ->setCode(AuthenticationResult::SUCCESS) ->setMessages(['Authentication successful.']); // recherche de l'individu dans l'annuaire LDAP (il existe forcément puisque l'auth CAS a réussi) $ldapPeople = $this->getLdapPeopleMapper()->findOneByUsername($identity->getUsername()); /* @var $userService User */ $this->userService->userAuthenticated($ldapPeople); return true; } /** * @inheritDoc */ public function logout(EventInterface $e) { parent::logout($e); $storage = $this->getStorage()->read(); if (! isset($storage['identity'])) { return; } $returnUrl = $this->router->getRequestUri()->setPath($this->router->getBaseUrl())->toString(); $this->getCasClient()->logoutWithRedirectService($returnUrl); } /** * Retourne le client CAS. * * @param boolean $initClient * @return phpCAS * @throws Exception */ public function getCasClient($initClient = true): phpCAS { if (null === $this->casClient) { $this->casClient = new phpCAS(); } if (!$initClient) { return $this->casClient; } if (null === $this->casOptions) { $config = $this->moduleOptions->getCas(); if (!isset($config['connection']['default']['params']) || !$config['connection']['default']['params']) { throw new Exception("Les paramètres de connexion au serveur CAS sont invalides."); } $this->casOptions = $config['connection']['default']['params']; } $options = $this->casOptions; if (array_key_exists('debug', $options) && (bool) $options['debug']) { $this->casClient->setDebug(); } // initialize phpCAS $this->casClient->client($options['version'], $options['hostname'], $options['port'], $options['uri'], true); // no SSL validation for the CAS server $this->casClient->setNoCasServerValidation(); return $this->casClient; } /** * Spécifie le client CAS. * * @param phpCAS $casClient * @return self */ public function setCasClient(phpCAS $casClient): self { $this->casClient = $casClient; return $this; } /** * get ldap people mapper * * @return LdapPeopleMapper */ public function getLdapPeopleMapper(): LdapPeopleMapper { return $this->ldapPeopleMapper; } /** * set ldap people mapper * * @param LdapPeopleMapper $mapper * @return self */ public function setLdapPeopleMapper(LdapPeopleMapper $mapper): self { $this->ldapPeopleMapper = $mapper; return $this; } /** * @param RouteInterface $router */ public function reconfigureRoutesForCasAuth(RouteInterface $router) { if(!$router instanceof RouteStackInterface) { return; } $router->addRoutes([ // remplace les routes existantes (cf. config du module) 'zfcuser' => [ 'type' => 'Literal', 'priority' => 1000, 'options' => [ 'route' => '/auth', 'defaults' => [ 'controller' => 'zfcuser', 'action' => 'index', ], ], 'may_terminate' => true, 'child_routes' => [ 'login' => [ 'type' => 'Segment', 'options' => [ 'route' => '/connexion[/:type]', 'defaults' => [ 'controller' => 'zfcuser', 'action' => 'authenticate', // zappe l'action 'login' ], ], ], 'logout' => [ 'type' => 'Literal', 'options' => [ 'route' => '/deconnexion', 'defaults' => [ 'controller' => 'zfcuser', 'action' => 'logout', ], ], ], ], ], ]); } }