Commit eefbdbc4 authored by Bertrand Gauthier's avatar Bertrand Gauthier
Browse files

Refactorisations.

parent 30760bf8
<?php
use UnicaenAuth\Authentication\Adapter\ShibSimulatorAdapter;
use UnicaenAuth\Authentication\Storage\ShibSimulatorStorage;
use UnicaenAuth\Controller\AuthControllerFactory;
use UnicaenAuth\Service\ShibService;
use UnicaenAuth\Service\ShibServiceFactory;
......@@ -374,6 +376,7 @@ return [
'UnicaenAuth\Authentication\Storage\Db' => 'UnicaenAuth\Authentication\Storage\Db',
'UnicaenAuth\Authentication\Storage\Ldap' => 'UnicaenAuth\Authentication\Storage\Ldap',
'UnicaenAuth\Authentication\Storage\Shib' => 'UnicaenAuth\Authentication\Storage\Shib',
'UnicaenAuth\Authentication\Storage\ShibSimulatorStorage' => ShibSimulatorStorage::class,
'UnicaenAuth\View\RedirectionStrategy' => 'UnicaenAuth\View\RedirectionStrategy',
'UnicaenAuth\Service\User' => 'UnicaenAuth\Service\User',
'UnicaenAuth\Service\CategoriePrivilege' => 'UnicaenAuth\Service\CategoriePrivilegeService',
......
......@@ -3,7 +3,6 @@
namespace UnicaenAuth\Authentication\Storage;
use UnicaenAuth\Entity\Shibboleth\ShibUser;
use UnicaenAuth\Options\ModuleOptions;
use UnicaenAuth\Service\ShibService;
use Zend\Authentication\Storage\Session;
use Zend\Authentication\Storage\StorageInterface;
......@@ -24,11 +23,6 @@ class Shib implements ChainableStorage, ServiceLocatorAwareInterface
* @var StorageInterface
*/
protected $storage;
/**
* @var ModuleOptions
*/
protected $options;
/**
* @var ShibUser
......@@ -63,10 +57,6 @@ class Shib implements ChainableStorage, ServiceLocatorAwareInterface
*/
private function getAuthenticatedUser()
{
if (! $this->isShibbolethEnabled()) {
return null;
}
if (null !== $this->resolvedIdentity) {
return $this->resolvedIdentity;
}
......@@ -79,29 +69,6 @@ class Shib implements ChainableStorage, ServiceLocatorAwareInterface
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
*
......
<?php
namespace UnicaenAuth\Authentication\Storage;
use UnicaenAuth\Service\ShibService;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorAwareTrait;
/**
* Storage permettant de simuler un utilisateur authentifié via Shibboleth.
*
* @author Unicaen
*/
class ShibSimulatorStorage implements ChainableStorage, ServiceLocatorAwareInterface
{
use ServiceLocatorAwareTrait;
/**
* @var ShibService
*/
protected $shibService;
/**
* @var array
*/
protected $shibbolethOptions;
/**
* {@inheritdoc}
*/
public function read(ChainEvent $e)
{
if (! $this->getShibService()->isShibbolethEnabled()) {
return;
}
if (! $this->getShibService()->isSimulationActive()) {
return;
}
$this->getShibService()->handleSimulation();
}
/**
* {@inheritdoc}
*/
public function write(ChainEvent $e)
{
// nop
}
/**
* {@inheritdoc}
*/
public function clear(ChainEvent $e)
{
// nop
}
/**
* @return ShibService
*/
private function getShibService()
{
if ($this->shibService === null) {
$this->shibService = $this->serviceLocator->get(ShibService::class);
}
return $this->shibService;
}
}
\ No newline at end of file
......@@ -3,7 +3,6 @@
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;
......@@ -24,15 +23,17 @@ 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.
* Cette action peut être appelée lorsque l'authentification Shibboleth est activée
* (unicaen-auth.shibboleth.enable === true).
*
* 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.
* > Si la config Apache de Shibboleth est correcte, une requête à l'adresse correspondant à cette action
* (suite au clic sur le bouton "Authentification Shibboleth", typiquement)
* est détournée par Apache pour réaliser l'authentification Shibboleth.
* Ce n'est qu'une fois l'authentification réalisée avec succès que cette action est appelée.
*
* @see ShibService::apacheConfigSnippet()
* > Si la config Apache de Shibboleth est incorrecte ou absente (localhost par exemple), et que la simulation
* Shibboleth est activée dans la config (unicaen-auth.shibboleth.simulate), cette action est appelée et
* la simulation est enclenchée.
*
* @return Response|array
*/
......@@ -41,44 +42,69 @@ class AuthController extends AbstractActionController
$operation = $this->params()->fromRoute('operation');
if ($operation === 'deconnexion') {
// déconnexion applicative quoiqu'il arrive
$this->zfcUserAuthentication()->getAuthAdapter()->resetAdapters();
$this->zfcUserAuthentication()->getAuthAdapter()->logoutAdapters();
$this->zfcUserAuthentication()->getAuthService()->clearIdentity();
// déconnexion Shibboleth le cas échéant
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
}
return $this->shibbolethLogout();
}
$shibUser = $this->shibService->getAuthenticatedUser();
$redirectUrl = $this->params()->fromQuery('redirect', '/');
// enclenchement de la simulation shibboleth éventuellement activée dans la config
if ($simulate = $this->shibService->getShibbolethSimulate()) {
$this->setStoredAuthenticatedUsername($simulate['eppn']); // tout simplement!
return $this->redirect()->toUrl($redirectUrl);
}
$shibUser = $this->shibService->getAuthenticatedUser();
if ($shibUser === null) {
return []; // une page d'aide s'affichera si les données issues de Shibboleth attendues sont absentes
}
// arrivé ici, l'authentification shibboleth a été faite en bonne et due forme et a réussie.
$this->setStoredAuthenticatedUsername($shibUser->getUsername());
$this->userService->userAuthenticated($shibUser);
return $this->redirect()->toUrl($redirectUrl);
}
/**
* Déconnexion Shibboleth.
*
* @return array|Response
*/
private function shibbolethLogout()
{
// déconnexion applicative quoiqu'il arrive
$this->zfcUserAuthentication()->getAuthAdapter()->resetAdapters();
$this->zfcUserAuthentication()->getAuthAdapter()->logoutAdapters();
$this->zfcUserAuthentication()->getAuthService()->clearIdentity();
// déconnexion Shibboleth le cas échéant
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
}
}
/**
* @param string $username
*/
private function setStoredAuthenticatedUsername($username)
{
/** @var AuthenticationService $authService */
$authService = $this->getServiceLocator()->get('zfcuser_auth_service');
try {
$authService->getStorage()->write($shibUser->getUsername());
$authService->getStorage()->write($username);
} catch (ExceptionInterface $e) {
throw new RuntimeException("Impossible d'écrire dans le storage");
}
$this->userService->userAuthenticated($shibUser);
$redirectUrl = $this->params()->fromQuery('redirect', '/');
return $this->redirect()->toUrl($redirectUrl);
}
}
\ No newline at end of file
......@@ -58,25 +58,11 @@ EOS;
}
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();
}
$this->handleUsurpation();
if (empty($_SERVER['REMOTE_USER'])) {
if ($this->isSimulationActive()) {
$this->handleSimulation();
} else {
return null;
}
return null;
}
$this->authenticatedUser = $this->createShibUserFromServerArrayData();
......@@ -114,7 +100,7 @@ EOS;
*
* @return bool
*/
private function isSimulationActive()
public function isSimulationActive()
{
$options = $this->options->getShibboleth();
......@@ -126,10 +112,17 @@ EOS;
}
/**
* @return $this
* @return ShibUser|null
*/
private function handleSimulation()
public function handleSimulation()
{
if (! $this->isSimulationActive()) {
return null;
}
// si nécessaire
$this->handleUsurpation();
$simulate = $this->getShibbolethSimulate();
try {
......@@ -154,9 +147,9 @@ EOS;
$shibUser->setNom('Shibboleth');
$shibUser->setPrenom('Simulation');
ShibService::simulateAuthenticatedUser($shibUser);
$this->simulateAuthenticatedUser($shibUser);
return $this;
return $shibUser;
}
/**
......@@ -205,8 +198,12 @@ EOS;
/**
* @return $this
*/
private function handleUsurpation()
public function handleUsurpation()
{
if (! $this->isUsurpationActive()) {
return $this;
}
$session = $this->getSessionContainer();
/** @var ShibUser|null $toShibUser */
......@@ -215,7 +212,7 @@ EOS;
throw new RuntimeException("Anomalie: 'toShibUser' introuvable");
}
static::simulateAuthenticatedUser($toShibUser, 'supannEmpId');
$this->simulateAuthenticatedUser($toShibUser, 'supannEmpId');
return $this;
}
......@@ -236,7 +233,7 @@ EOS;
* @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')
public function simulateAuthenticatedUser(ShibUser $shibUser, $keyForId = 'supannEmpId')
{
$_SERVER['REMOTE_USER'] = $shibUser->getEppn();
$_SERVER[$keyForId] = $shibUser->getId();
......
<h1 class="page-header">Authentification Shibboleth</h1>
<p>
Si vous arrivez sur cette page, c'est sans doute que vous cherchez à utiliser l'authentification Shibboleth, mais
qu'elle est mal configurée !
</p>
<h2>Configuration pour Shibboleth</h2>
<p>
Vous devez activer l'authentification Shibboleth dans la config :
Déjà, vous devez activer l'authentification Shibboleth dans la config de UnicaenAuth :
</p>
<pre>
'unicaen-auth' => [
...
'shibboleth' => [
'enable' => true
'enable' => true,
],
];
],
</pre>
<p>
Et voici ce que vous devez ajouter dans la configuration Apache de votre site :
</p>
<pre><?php echo htmlspecialchars(\UnicaenAuth\Service\ShibService::apacheConfigSnippet()) ?></pre>
\ No newline at end of file
<pre><?php echo htmlspecialchars(\UnicaenAuth\Service\ShibService::apacheConfigSnippet()) ?></pre>
<h2>Autre solution : simuler une authentification Shibboleth</h2>
<p>
Il est possible de faire comme si un utilisateur s'était connecté via Shibboleth.
Cela se fait via la clé de config 'simulate' :
</p>
<pre>
'unicaen-auth' => [
...
'shibboleth' => [
'enable' => true,
'simulate' => [
'eppn' => 'gauthierb@unicaen.fr',
'supannEmpId' => '00021237',
],
],
],
</pre>
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment