Skip to content
Snippets Groups Projects
Commit 5e8ee47f authored by Bertrand Gauthier's avatar Bertrand Gauthier
Browse files

Simplifications autour de la simulation d'une authentification shibboleth.

parent cb761a71
No related branches found
No related tags found
No related merge requests found
Pipeline #3488 failed
<?php
use UnicaenAuth\Authentication\Storage\ShibSimulatorStorage;
use UnicaenAuth\Controller\AuthControllerFactory;
use UnicaenAuth\Service\ShibService;
use UnicaenAuth\Service\ShibServiceFactory;
......@@ -424,7 +423,6 @@ 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',
......
......@@ -16,7 +16,6 @@ class ChainServiceFactory implements FactoryInterface
private $mandatoryStorages = [
200 => 'UnicaenAuth\Authentication\Storage\Ldap',
100 => 'UnicaenAuth\Authentication\Storage\Db',
76 => 'UnicaenAuth\Authentication\Storage\ShibSimulatorStorage',
75 => 'UnicaenAuth\Authentication\Storage\Shib',
];
......
<?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
......@@ -55,19 +55,12 @@ class AuthController extends AbstractActionController
$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.
// arrivé ici, l'authentification shibboleth a été faite (réellement ou simulée) et a réussie.
$this->setStoredAuthenticatedUsername($shibUser->getUsername());
$this->userService->userAuthenticated($shibUser);
......
......@@ -2,9 +2,9 @@
namespace UnicaenAuth\Service;
use InvalidArgumentException;
use Assert\Assertion;
use Assert\AssertionFailedException;
use InvalidArgumentException;
use UnicaenApp\Exception\LogicException;
use UnicaenApp\Exception\RuntimeException;
use UnicaenAuth\Entity\Shibboleth\ShibUser;
......@@ -79,11 +79,12 @@ EOS;
}
if ($this->authenticatedUser === null) {
// gestion de l'usurpation éventuelle
// activation éventuelle de l'usurpation
$this->handleUsurpation();
if (! $this->getServerArrayVariable('eppn')) {
return null;
}
// activation éventuelle de la simulation
$this->handleSimulation();
$this->authenticatedUser = $this->createShibUserFromServerArrayData();
}
......@@ -175,44 +176,51 @@ EOS;
}
/**
* @return ShibUser|null
*
*/
public function handleSimulation()
{
if (! $this->isSimulationActive()) {
return null;
return;
}
// si nécessaire
$this->handleUsurpation();
$simulate = $this->getShibbolethSimulate();
try {
Assertion::keyIsset($simulate, 'eppn',
"Clé 'eppn' introuvable ou sans valeur dans l'option 'unicaen-auth.shibboleth.simulate'");
Assertion::contains($simulate['eppn'], '@',
"L'eppn '" . $simulate['eppn'] . "' n'est pas de la forme 'id@domaine' attendue (ex: 'tartempion@unicaen.fr')");
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));
$shibUser = $this->createShibUserFromSimulationData();
} 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;
$this->simulateAuthenticatedUser($shibUser);
}
/**
* @return ShibUser
* @throws AssertionFailedException
*/
private function createShibUserFromSimulationData()
{
$data = $this->getShibbolethSimulate();
$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);
$surname = $this->getValueFromShibData('sn', $data);
$civilite = $this->getValueFromShibData('supannCivilite', $data);
Assertion::contains($eppn, '@', "L'eppn '" . $eppn . "' n'est pas de la forme 'id@domaine' attendue (ex: 'tartempion@unicaen.fr')");
$shibUser = new ShibUser();
$shibUser->setEppn($eppn);
$shibUser->setId($supannId);
$shibUser->setDisplayName("$eppn ($supannId)");
$shibUser->setDisplayName($displayName);
$shibUser->setEmail($email);
$shibUser->setNom('Shibboleth');
$shibUser->setPrenom('Simulation');
$this->simulateAuthenticatedUser($shibUser);
$shibUser->setNom($surname);
$shibUser->setPrenom($givenName);
$shibUser->setCivilite($civilite);
return $shibUser;
}
......@@ -344,10 +352,14 @@ EOS;
*/
public function simulateAuthenticatedUser(ShibUser $shibUser, $keyForId = 'supannEmpId')
{
// on s'assure que tous les attributs obligatoires ont une valeur
foreach ($this->getShibbolethRequiredAttributes() as $attribute) {
$this->setServerArrayVariable($attribute, 'qqchose');
}
// // 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());
......@@ -356,6 +368,7 @@ EOS;
$this->setServerArrayVariable('mail', $shibUser->getEppn());
$this->setServerArrayVariable('sn', $shibUser->getNom());
$this->setServerArrayVariable('givenName', $shibUser->getPrenom());
$this->setServerArrayVariable('supannCivilite', $shibUser->getCivilite());
}
/**
......@@ -461,6 +474,22 @@ EOS;
]);
}
/**
* @param string $name
* @param array $data
* @return string
*/
private function getValueFromShibData($name, array $data)
{
$key = $this->getShibbolethAliasFor($name) ?: $name;
if (! array_key_exists($key, $data)) {
return null;
}
return $data[$key];
}
/**
* @param string $name
* @param string $value
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment