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

Merge branch 'release-3.2.0'

parents 098e285b 23c62cc7
Pipeline #9950 passed with stage
in 16 seconds
...@@ -37,3 +37,11 @@ Première version officielle sous ZF3. ...@@ -37,3 +37,11 @@ Première version officielle sous ZF3.
3.1.2 3.1.2
----- -----
- Aide de vue UserUsurpationHelper : ajout de la possibilité de dessiner un simple bouton. - Aide de vue UserUsurpationHelper : ajout de la possibilité de dessiner un simple bouton.
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.
...@@ -75,15 +75,6 @@ class Module implements AutoloaderProviderInterface, ConfigProviderInterface, Se ...@@ -75,15 +75,6 @@ class Module implements AutoloaderProviderInterface, ConfigProviderInterface, Se
}, },
//=========================================== //===========================================
// verrue pour forcer le label de l'identifiant qqsoit l'options 'auth_identity_fields'
'zfcuser_login_form' => function ($sm) {
$options = $sm->get('zfcuser_module_options');
$form = new Login(null, $options);
$form->setInputFilter(new LoginFilter($options));
$form->get('identity')->setLabel("Username");
return $form;
},
], ],
]; ];
} }
......
<?php <?php
use UnicaenAuth\Authentication\Adapter\AdapterChainServiceFactory; use UnicaenAuth\Authentication\Adapter\AdapterChainServiceFactory;
use UnicaenAuth\Authentication\Adapter\Cas;
use UnicaenAuth\Authentication\Adapter\CasAdapterFactory; use UnicaenAuth\Authentication\Adapter\CasAdapterFactory;
use UnicaenAuth\Authentication\Adapter\Db;
use UnicaenAuth\Authentication\Adapter\DbAdapterFactory; use UnicaenAuth\Authentication\Adapter\DbAdapterFactory;
use UnicaenAuth\Authentication\Adapter\Ldap;
use UnicaenAuth\Authentication\Adapter\LdapAdapterFactory; use UnicaenAuth\Authentication\Adapter\LdapAdapterFactory;
use UnicaenAuth\Authentication\Adapter\LocalAdapter;
use UnicaenAuth\Authentication\Adapter\LocalAdapterFactory;
use UnicaenAuth\Authentication\Adapter\Shib;
use UnicaenAuth\Authentication\Adapter\ShibAdapterFactory; use UnicaenAuth\Authentication\Adapter\ShibAdapterFactory;
use UnicaenAuth\Authentication\Storage\Auth;
use UnicaenAuth\Authentication\Storage\AuthFactory;
use UnicaenAuth\Authentication\Storage\DbFactory; use UnicaenAuth\Authentication\Storage\DbFactory;
use UnicaenAuth\Authentication\Storage\LdapFactory; use UnicaenAuth\Authentication\Storage\LdapFactory;
use UnicaenAuth\Authentication\Storage\ShibFactory; use UnicaenAuth\Authentication\Storage\ShibFactory;
use UnicaenAuth\Authentication\Storage\Usurpation;
use UnicaenAuth\Authentication\Storage\UsurpationFactory;
use UnicaenAuth\Controller\AuthControllerFactory; use UnicaenAuth\Controller\AuthControllerFactory;
use UnicaenAuth\Controller\DroitsControllerFactory; use UnicaenAuth\Controller\DroitsControllerFactory;
use UnicaenAuth\Controller\UtilisateurControllerFactory; use UnicaenAuth\Controller\UtilisateurControllerFactory;
use UnicaenAuth\Form\CasLoginForm; use UnicaenAuth\Form\CasLoginForm;
use UnicaenAuth\Form\CasLoginFormFactory; use UnicaenAuth\Form\CasLoginFormFactory;
use UnicaenAuth\Form\Droits\RoleFormFactory; use UnicaenAuth\Form\Droits\RoleFormFactory;
use UnicaenAuth\Form\LoginFormFactory;
use UnicaenAuth\Form\LoginForm;
use UnicaenAuth\Form\ShibLoginForm; use UnicaenAuth\Form\ShibLoginForm;
use UnicaenAuth\Form\ShibLoginFormFactory; use UnicaenAuth\Form\ShibLoginFormFactory;
use UnicaenAuth\Guard\PrivilegeControllerFactory; use UnicaenAuth\Guard\PrivilegeControllerFactory;
...@@ -59,9 +71,9 @@ use Zend\ServiceManager\Proxy\LazyServiceFactory; ...@@ -59,9 +71,9 @@ use Zend\ServiceManager\Proxy\LazyServiceFactory;
$settings = [ $settings = [
/** /**
* Configuration de l'authentification via la fédération d'identité (Shibboleth). * Configuration de l'authentification centralisée (CAS).
*/ */
'shib' => [ 'cas' => [
/** /**
* Ordre d'affichage du formulaire de connexion. * Ordre d'affichage du formulaire de connexion.
*/ */
...@@ -70,12 +82,77 @@ $settings = [ ...@@ -70,12 +82,77 @@ $settings = [
/** /**
* Activation ou non de ce mode d'authentification. * Activation ou non de ce mode d'authentification.
*/ */
'enabled' => false, 'enabled' => true,
/**
* Description facultative de ce mode d'authentification qui apparaîtra sur la page de connexion.
*/
'description' => "Cliquez sur le bouton ci-dessous pour accéder à l'authentification centralisée.",
/**
* Adapter compétent pour réaliser l'authentification de l'utilisateur.
*/
'adapter' => Cas::class,
/**
* Service/formulaire d'authentification à utiliser.
*/
'form' => CasLoginForm::class,
/** /**
* Description facultative de ce mode d'authentification qui apparaîtra sur le formulaire de connexion. * Infos de connexion au serveur CAS.
*/ */
'connection' => [
'default' => [
'params' => [
'hostname' => 'host.domain.fr',
'port' => 443,
'version' => "2.0",
'uri' => "",
'debug' => false,
],
],
]
],
/**
* Configuration de l'authentification locale (compte LDAP établissement, ou compte BDD application).
*/
'local' => [
'order' => 2,
'enabled' => true,
'description' => "Utilisez ce formulaire si vous possédez un compte LDAP établissement ou un compte local dédié à l'application.",
'form' => LoginForm::class,
/**
* Mode d'authentification à l'aide d'un compte dans la BDD de l'application.
*/
'db' => [
'enabled' => true, // doit être activé pour que l'usurpation fonctionne (cf. Authentication/Storage/Db::read()) :-/ todo: faire mieux
'adapter' => Db::class,
'form' => LoginForm::class,
],
/**
* Mode d'authentification à l'aide d'un compte LDAP.
*/
'ldap' => [
'enabled' => true,
'adapter' => Ldap::class,
'form' => LoginForm::class,
],
],
/**
* Configuration de l'authentification via la fédération d'identité (Shibboleth).
*/
'shib' => [
'order' => 3,
'enabled' => false,
'description' => "Cliquez sur le bouton ci-dessous pour accéder à l'authentification via la fédération d'identité.", 'description' => "Cliquez sur le bouton ci-dessous pour accéder à l'authentification via la fédération d'identité.",
'adapter' => Shib::class,
'form' => ShibLoginForm::class,
/** /**
* URL de déconnexion. * URL de déconnexion.
...@@ -110,68 +187,33 @@ $settings = [ ...@@ -110,68 +187,33 @@ $settings = [
'supannEtuId|supannEmpId', 'supannEtuId|supannEmpId',
], ],
*/ */
],
/**
* Configuration de l'authentification LDAP (compte établissement).
*/
'ldap' => [
'order' => 2,
'enabled' => true,
'description' => "Utilisez ce formulaire pour vous connecter avec votre compte numérique établissement.",
/**
* Type de substitution.
* Permet de "fusionner" les types d'authentification locale (db) et établissement (ldap) et donc leurs
* formulaires de connexion respectifs.
*/
'type' => 'local',
],
/**
* Configuration de l'authentification locale (compte propre à l'appli).
*/
'db' => [
'order' => 3,
'enabled' => false,
/**
* Type de substitution.
* Permet de "grouper" les types d'authentification locale (db) et établissement (ldap) sous un même
* formulaire de connexion.
*/
'type' => 'local',
/** /**
* Description facultative de ce mode d'authentification qui apparaîtra sur le formulaire d'authentification. * Configuration de la stratégie d'extraction d'un identifiant utile parmi les données d'authentification
* NB: si la valeur de 'order' pour le type 'db' est supérieure à celle pour le type 'ldap', * shibboleth.
* c'est cette description qui sera visible. * Ex: identifiant de l'usager au sein du référentiel établissement, transmis par l'IDP via le supannRefId.
*/ */
'description' => "Utilisez ce formulaire si vous possédez un compte local propre à l'application.", 'shib_user_id_extractor' => [
], // domaine (ex: 'unicaen.fr') de l'EPPN (ex: hochonp@unicaen.fr')
'unicaen.fr' => [
/** [
* Configuration de l'authentification centralisée (CAS). // nom du 1er attribut recherché
*/ 'name' => 'supannRefId', // ex: '{REFERENTIEL}1234;{ISO15693}044D1AZE7A5P80'
'cas' => [ // pattern éventuel pour extraire la partie intéressante
'order' => 4, 'preg_match_pattern' => '|\{REFERENTIEL\}(\d+)|', // ex: permet d'extraire '1234'
'enabled' => false, ],
'description' => "Cliquez sur le bouton ci-dessous pour accéder à l'authentification centralisée.", [
// nom du 2e attribut recherché
/** 'name' => 'supannEmpId',
* Infos de connexion au serveur CAS. // pas de pattern donc valeur directement utilisable
*/ 'preg_match_pattern' => null,
'connection' => [ ],
'default' => [ [
'params' => [ // nom du 3e attribut recherché
'hostname' => 'host.domain.fr', 'name' => 'supannEtuId',
'port' => 443,
'version' => "2.0",
'uri' => "",
'debug' => false,
], ],
], ],
] ],
], ],
/** /**
...@@ -239,9 +281,8 @@ return [ ...@@ -239,9 +281,8 @@ return [
* Default value: array containing 'ZfcUser\Authentication\Adapter\Db' with priority 100 * Default value: array containing 'ZfcUser\Authentication\Adapter\Db' with priority 100
* Accepted values: array containing services that implement 'ZfcUser\Authentication\Adapter\ChainableAdapter' * Accepted values: array containing services that implement 'ZfcUser\Authentication\Adapter\ChainableAdapter'
*/ */
'auth_adapters' => [ 'auth_adapters' => [
300 => 'UnicaenAuth\Authentication\Adapter\Ldap', 400 => LocalAdapter::class, // délègue à Db et Ldap
200 => 'UnicaenAuth\Authentication\Adapter\Db',
100 => 'UnicaenAuth\Authentication\Adapter\Cas', 100 => 'UnicaenAuth\Authentication\Adapter\Cas',
50 => 'UnicaenAuth\Authentication\Adapter\Shib', 50 => 'UnicaenAuth\Authentication\Adapter\Shib',
], ],
...@@ -295,6 +336,8 @@ return [ ...@@ -295,6 +336,8 @@ return [
['controller' => 'UnicaenApp\Controller\Application', 'action' => 'informatique-et-libertes', 'roles' => 'guest'], ['controller' => 'UnicaenApp\Controller\Application', 'action' => 'informatique-et-libertes', 'roles' => 'guest'],
['controller' => 'UnicaenApp\Controller\Application', 'action' => 'refresh-session', 'roles' => 'guest'], ['controller' => 'UnicaenApp\Controller\Application', 'action' => 'refresh-session', 'roles' => 'guest'],
['controller' => 'UnicaenAuth\Controller\Utilisateur', 'action' => 'selectionner-profil', 'roles' => 'guest'], ['controller' => 'UnicaenAuth\Controller\Utilisateur', 'action' => 'selectionner-profil', 'roles' => 'guest'],
['controller' => 'UnicaenAuth\Controller\Utilisateur', 'action' => 'usurper-identite', 'roles' => 'guest'],
['controller' => 'UnicaenAuth\Controller\Utilisateur', 'action' => 'stopper-usurpation', 'roles' => 'guest'],
['controller' => 'UnicaenAuth\Controller\Auth', 'action' => 'login', 'roles' => 'guest'], ['controller' => 'UnicaenAuth\Controller\Auth', 'action' => 'login', 'roles' => 'guest'],
['controller' => 'UnicaenAuth\Controller\Auth', 'action' => 'authenticate', 'roles' => 'guest'], ['controller' => 'UnicaenAuth\Controller\Auth', 'action' => 'authenticate', 'roles' => 'guest'],
...@@ -575,6 +618,7 @@ return [ ...@@ -575,6 +618,7 @@ return [
// in /var/www/sygal/module/Application/src/Application/Controller/UtilisateurController.php on line 34 // in /var/www/sygal/module/Application/src/Application/Controller/UtilisateurController.php on line 34
'service_manager' => [ 'service_manager' => [
'aliases' => [ 'aliases' => [
'zfcuser_login_form' => LoginForm::class,
'Zend\Authentication\AuthenticationService' => 'zfcuser_auth_service', 'Zend\Authentication\AuthenticationService' => 'zfcuser_auth_service',
'UnicaenAuth\Privilege\PrivilegeProvider' => 'UnicaenAuth\Service\Privilege', 'UnicaenAuth\Privilege\PrivilegeProvider' => 'UnicaenAuth\Service\Privilege',
'\UnicaenAuth\Guard\PrivilegeController' => 'UnicaenAuth\Guard\PrivilegeController', '\UnicaenAuth\Guard\PrivilegeController' => 'UnicaenAuth\Guard\PrivilegeController',
...@@ -607,6 +651,7 @@ return [ ...@@ -607,6 +651,7 @@ return [
'UnicaenAuth\Service\UserContext' => UserContextFactory::class, 'UnicaenAuth\Service\UserContext' => UserContextFactory::class,
'zfcuser_user_mapper' => UserMapperFactory::class, 'zfcuser_user_mapper' => UserMapperFactory::class,
'MouchardCompleterAuth' => 'UnicaenAuth\Mouchard\MouchardCompleterAuthFactory', 'MouchardCompleterAuth' => 'UnicaenAuth\Mouchard\MouchardCompleterAuthFactory',
LocalAdapter::class => LocalAdapterFactory::class,
'UnicaenAuth\Authentication\Adapter\Ldap' => LdapAdapterFactory::class, 'UnicaenAuth\Authentication\Adapter\Ldap' => LdapAdapterFactory::class,
'UnicaenAuth\Authentication\Adapter\Db' => DbAdapterFactory::class, 'UnicaenAuth\Authentication\Adapter\Db' => DbAdapterFactory::class,
'UnicaenAuth\Authentication\Adapter\Cas' => CasAdapterFactory::class, 'UnicaenAuth\Authentication\Adapter\Cas' => CasAdapterFactory::class,
...@@ -614,11 +659,16 @@ return [ ...@@ -614,11 +659,16 @@ return [
'UnicaenAuth\Authentication\Storage\Db' => DbFactory::class, 'UnicaenAuth\Authentication\Storage\Db' => DbFactory::class,
'UnicaenAuth\Authentication\Storage\Ldap' => LdapFactory::class, 'UnicaenAuth\Authentication\Storage\Ldap' => LdapFactory::class,
'UnicaenAuth\Authentication\Storage\Shib' => ShibFactory::class, 'UnicaenAuth\Authentication\Storage\Shib' => ShibFactory::class,
Usurpation::class => UsurpationFactory::class,
Auth::class => AuthFactory::class,
'UnicaenAuth\Service\User' => UserFactory::class, 'UnicaenAuth\Service\User' => UserFactory::class,
'UnicaenAuth\Guard\PrivilegeController' => PrivilegeControllerFactory::class, 'UnicaenAuth\Guard\PrivilegeController' => PrivilegeControllerFactory::class,
'UnicaenAuth\Guard\PrivilegeRoute' => PrivilegeRouteFactory::class, 'UnicaenAuth\Guard\PrivilegeRoute' => PrivilegeRouteFactory::class,
'UnicaenAuth\Provider\Rule\PrivilegeRuleProvider' => PrivilegeRuleProviderFactory::class, 'UnicaenAuth\Provider\Rule\PrivilegeRuleProvider' => PrivilegeRuleProviderFactory::class,
// verrue pour forcer le label de l'identifiant qqsoit l'options 'auth_identity_fields'
LoginForm::class => LoginFormFactory::class,
CasLoginForm::class => CasLoginFormFactory::class, CasLoginForm::class => CasLoginFormFactory::class,
ShibLoginForm::class => ShibLoginFormFactory::class, ShibLoginForm::class => ShibLoginFormFactory::class,
'ZfcUser\Authentication\Adapter\AdapterChain' => AdapterChainServiceFactory::class, 'ZfcUser\Authentication\Adapter\AdapterChain' => AdapterChainServiceFactory::class,
......
<?php <?php
use UnicaenAuth\Authentication\Adapter\Shib;
use UnicaenAuth\Authentication\Adapter\Cas;
use UnicaenAuth\Authentication\Adapter\Ldap;
use UnicaenAuth\Authentication\Adapter\Db;
return [ return [
'unicaen-auth' => [ 'unicaen-auth' => [
/** /**
* Authentification LDAP (compte établissement). * Configuration de l'authentification centralisée (CAS).
*/ */
'ldap' => [ 'cas' => [
/** /**
* Ordre d'affichage du formulaire de connexion. * Ordre d'affichage du formulaire de connexion.
*/ */
...@@ -23,39 +18,9 @@ return [ ...@@ -23,39 +18,9 @@ return [
'enabled' => true, 'enabled' => true,
/** /**
* Type de substitution. * Description facultative de ce mode d'authentification qui apparaîtra sur la page de connexion.
* Permet de "fusionner" les types d'authentification applicative (db) et établissement (ldap) et donc leurs
* formulaires de connexion respectifs.
*/
'type' => 'local',
/**
* Description facultative de ce mode d'authentification qui apparaîtra sur le formulaire de connexion.
*/ */
'description' => "Utilisez ce formulaire si vous possédez un compte établissement.", 'description' => "Cliquez sur le bouton ci-dessous pour accéder à l'authentification centralisée.",
],
/**
* Authentification BDD (compte dédié à l'appli).
*/
'db' => [
'order' => 2,
'enabled' => true,
'type' => 'local',
/**
* Description facultative de ce mode d'authentification qui apparaîtra sur le formulaire d'authentification.
* (NB: Si l'authentification LDAP est également activée, c'est cette description qui sera utilisée)
*/
'description' => "Utilisez ce formulaire si vous possédez un compte local dédié à cette application.",
],
/**
* Authentification centralisée (CAS).
*/
'cas' => [
'order' => 3,
'enabled' => false,
/** /**
* Infos de connexion au serveur CAS. * Infos de connexion au serveur CAS.
...@@ -70,6 +35,28 @@ return [ ...@@ -70,6 +35,28 @@ return [
'debug' => false, 'debug' => false,
], ],
], ],
]
],
/**
* Configuration de l'authentification locale (compte LDAP établissement, ou compte BDD application).
*/
'local' => [
'order' => 2,
'enabled' => true,
'description' => "Utilisez ce formulaire si vous possédez un compte LDAP établissement ou un compte local dédié à l'application.",
/**
* Mode d'authentification à l'aide d'un compte dans la BDD de l'application.
*/
'db' => [
'enabled' => true, // doit être activé pour que l'usurpation fonctionne (cf. Authentication/Storage/Db::read()) :-/
],
/**
* Mode d'authentification à l'aide d'un compte LDAP.
*/
'ldap' => [
'enabled' => true,
], ],
], ],
...@@ -77,7 +64,7 @@ return [ ...@@ -77,7 +64,7 @@ return [
* Authentification via la fédération d'identité (Shibboleth). * Authentification via la fédération d'identité (Shibboleth).
*/ */
'shib' => [ 'shib' => [
'order' => 4, 'order' => 3,
'enabled' => false, 'enabled' => false,
'description' => 'description' =>
"Cliquez sur le bouton ci-dessous pour accéder à l'authentification via la fédération d'identité. " . "Cliquez sur le bouton ci-dessous pour accéder à l'authentification via la fédération d'identité. " .
...@@ -128,6 +115,33 @@ return [ ...@@ -128,6 +115,33 @@ return [
// 'givenName', // 'givenName',
// 'supannEtuId|supannEmpId', // '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: '{REFERENTIEL}1234;{ISO15693}044D1AZE7A5P80'
// pattern éventuel pour extraire la partie intéressante
'preg_match_pattern' => '|\{REFERENTIEL\}(\d+)|', // ex: permet d'extraire '1234'
],
[
// nom du 2e attribut recherché
'name' => 'supannEmpId',
// pas de pattern donc valeur directement utilisable
'preg_match_pattern' => null,
],
[
// nom du 3e attribut recherché
'name' => 'supannEtuId',
],
],
],
], ],
/** /**
......
...@@ -2,18 +2,25 @@ ...@@ -2,18 +2,25 @@
namespace UnicaenAuth\Authentication\Adapter; namespace UnicaenAuth\Authentication\Adapter;
use Zend\Authentication\Storage; use UnicaenAuth\Authentication\SessionIdentity;
use Zend\Authentication\Storage\StorageInterface;
use Zend\EventManager\EventInterface;
use Zend\EventManager\EventManagerInterface;
use Zend\EventManager\ListenerAggregateInterface;
use Zend\EventManager\ListenerAggregateTrait;
use ZfcUser\Authentication\Adapter\ChainableAdapter; use ZfcUser\Authentication\Adapter\ChainableAdapter;
abstract class AbstractAdapter implements ChainableAdapter abstract class AbstractAdapter implements ChainableAdapter, ListenerAggregateInterface
{ {
use ListenerAggregateTrait;
/** /**
* @var string * @var string
*/ */
protected $type; protected $type;
/** /**
* @var Storage\StorageInterface * @var StorageInterface
*/ */
protected $storage; protected $storage;
...@@ -27,29 +34,31 @@ abstract class AbstractAdapter implements ChainableAdapter ...@@ -27,29 +34,31 @@ abstract class AbstractAdapter implements ChainableAdapter
return $this; return $this;
} }
/**
* @return string
*/
public function getType(): string
{
return $this->type;
}
/** /**
* Returns the persistent storage handler * Returns the persistent storage handler
* *
* Session storage is used by default unless a different storage adapter has been set. * @return StorageInterface
*
* @return Storage\StorageInterface
*/ */
public function getStorage() public function getStorage(): StorageInterface
{ {
if (null === $this->storage) {
$this->setStorage(new Storage\Session(get_class($this)));
}
return $this->storage; return $this->storage;
} }
/** /**
* Sets the persistent storage handler * Sets the persistent storage handler
* *
* @param Storage\StorageInterface $storage * @param StorageInterface $storage
* @return AbstractAdapter Provides a fluent interface * @return self Provides a fluent interface
*/ */
public function setStorage(Storage\StorageInterface $storage) public function setStorage(StorageInterface $storage): self
{ {
$this->storage = $storage; $this->storage = $storage;
return $this; return $this;
...@@ -60,7 +69,7 @@ abstract class AbstractAdapter implements ChainableAdapter ...@@ -60,7 +69,7 @@ abstract class AbstractAdapter implements ChainableAdapter
* *
* @return bool * @return bool