Commit 4d43239a authored by Bertrand Gauthier's avatar Bertrand Gauthier
Browse files

Modifications/améliorations pour faciliter le support d'autres modes...

Modifications/améliorations pour faciliter le support d'autres modes d'authentification (ex: unicaen/auth-token).
parent 5958fd68
Loading
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -3,8 +3,10 @@ CHANGELOG

3.2.1
-----
- Modifications/améliorations pour faciliter le support d'autres modes d'authentification (ex: unicaen/auth-token). 
- Le type d'authentification souhaité (local, shib ou cas) peut être spécifié dans l'URL de redirection via le 
  query param 'authtype'
- Ajout de la colonne CREATED_AT dans les scripts SQL de création de la table USER (non mappée dans l'entité).  
- [FIX] Usurpation d'un compte local (db) depuis une authentification shib
- [FIX] Une chaîne vide doit être considérée comme null dans ShibService::extractShibUserIdValueForDomainFromShibData()
- [FIX] Nécessité de clés littérales dans la config par domaine de 'shib_user_id_extractor' sinon doublons lors de la 
+22 −6
Original line number Diff line number Diff line
<?php

namespace UnicaenAuth;

use UnicaenAuth\Authentication\Adapter\AdapterChainServiceFactory;
use UnicaenAuth\Authentication\Adapter\Cas;
use UnicaenAuth\Authentication\Adapter\CasAdapterFactory;
@@ -18,6 +20,7 @@ use UnicaenAuth\Authentication\Storage\LdapFactory;
use UnicaenAuth\Authentication\Storage\ShibFactory;
use UnicaenAuth\Authentication\Storage\Usurpation;
use UnicaenAuth\Authentication\Storage\UsurpationFactory;
use UnicaenAuth\Controller\AuthController;
use UnicaenAuth\Controller\AuthControllerFactory;
use UnicaenAuth\Controller\DroitsControllerFactory;
use UnicaenAuth\Controller\UtilisateurControllerFactory;
@@ -30,12 +33,14 @@ use UnicaenAuth\Form\ShibLoginForm;
use UnicaenAuth\Form\ShibLoginFormFactory;
use UnicaenAuth\Guard\PrivilegeControllerFactory;
use UnicaenAuth\Guard\PrivilegeRouteFactory;
use UnicaenAuth\Options\ModuleOptions;
use UnicaenAuth\ORM\Event\Listeners\HistoriqueListenerFactory;
use UnicaenAuth\Provider\Rule\PrivilegeRuleProviderFactory;
use UnicaenAuth\Service\CasService;
use UnicaenAuth\Service\CasServiceFactory;
use UnicaenAuth\Service\ShibService;
use UnicaenAuth\Service\ShibServiceFactory;
use UnicaenAuth\Service\UserContext;
use UnicaenAuth\Service\UserContextFactory;
use UnicaenAuth\Service\UserFactory;
use UnicaenAuth\Service\UserMapperFactory;
@@ -70,6 +75,15 @@ use Zend\Authentication\AuthenticationService;
use Zend\ServiceManager\Proxy\LazyServiceFactory;

$settings = [
    /**
     * Tous les types d'authentification supportés par le module unicaen/auth.
     */
    'auth_types' => [
        'local', // càd 'ldap' et 'db'
        'cas',
        'shib',
    ],

    /**
     * Configuration de l'authentification centralisée (CAS).
     */
@@ -629,21 +643,22 @@ return [
    // in /var/www/sygal/module/Application/src/Application/Controller/UtilisateurController.php on line 34
    'service_manager' => [
        'aliases'            => [
            'unicaen-auth_module_options' => ModuleOptions::class,
            'zfcuser_login_form' => LoginForm::class,
            'Zend\Authentication\AuthenticationService' => 'zfcuser_auth_service',
            'UnicaenAuth\Privilege\PrivilegeProvider'   => 'UnicaenAuth\Service\Privilege',
            '\UnicaenAuth\Guard\PrivilegeController'    => 'UnicaenAuth\Guard\PrivilegeController',

            'unicaen-auth_user_service'               => 'UnicaenAuth\Service\User', // pour la compatibilité
            'authUserContext'                         => 'UnicaenAuth\Service\UserContext', // pour la compatibilité
            'AuthUserContext'                         => 'UnicaenAuth\Service\UserContext', // pour la compatibilité
            'authUserContext'                         => UserContext::class, // pour la compatibilité
            'AuthUserContext'                         => UserContext::class, // pour la compatibilité
        ],
        'invokables'         => [
            'UnicaenAuth\View\RedirectionStrategy'    => 'UnicaenAuth\View\RedirectionStrategy',
            'UnicaenAuth\Service\CategoriePrivilege'  => 'UnicaenAuth\Service\CategoriePrivilegeService',
        ],
        'factories'          => [
            'unicaen-auth_module_options'              => 'UnicaenAuth\Options\ModuleOptionsFactory',
            ModuleOptions::class                       => 'UnicaenAuth\Options\ModuleOptionsFactory',
            'zfcuser_auth_service'                     => 'UnicaenAuth\Authentication\AuthenticationServiceFactory',
            'UnicaenAuth\Authentication\Storage\Chain' => 'UnicaenAuth\Authentication\Storage\ChainServiceFactory',
            'UnicaenAuth\Provider\Identity\Chain'      => 'UnicaenAuth\Provider\Identity\ChainServiceFactory',
@@ -659,7 +674,7 @@ return [
            'zfcuser_redirect_callback'                => 'UnicaenAuth\Authentication\RedirectCallbackFactory', // substituion
            CasService::class                          => CasServiceFactory::class,
            ShibService::class                         => ShibServiceFactory::class,
            'UnicaenAuth\Service\UserContext'          => UserContextFactory::class,
            UserContext::class                         => UserContextFactory::class,
            'zfcuser_user_mapper'                      => UserMapperFactory::class,
            'MouchardCompleterAuth'        => 'UnicaenAuth\Mouchard\MouchardCompleterAuthFactory',
            LocalAdapter::class => LocalAdapterFactory::class,
@@ -708,10 +723,11 @@ return [
    ],

    'controllers'   => [
        'invokables' => [
        'aliases' => [
            'UnicaenAuth\Controller\Auth' => AuthController::class,
        ],
        'factories' => [
            'UnicaenAuth\Controller\Auth'        => AuthControllerFactory::class,
            AuthController::class => AuthControllerFactory::class,
            'UnicaenAuth\Controller\Utilisateur' => UtilisateurControllerFactory::class,
            'UnicaenAuth\Controller\Droits'      => DroitsControllerFactory::class,
        ],
+125 −0
Original line number Diff line number Diff line
<?php

namespace UnicaenAuth\Authentication\Adapter;

use UnicaenAuth\Options\Traits\ModuleOptionsAwareTrait;
use Zend\Authentication\Result as AuthenticationResult;
use Zend\EventManager\EventInterface;
use Zend\Session\Container as SessionContainer;
use ZfcUser\Authentication\Adapter\AdapterChainEvent;
use ZfcUser\Entity\UserInterface;
use ZfcUser\Mapper\UserInterface as UserMapperInterface;

/**
 * Classe abstraite des adpater d'authentification à partir de la base de données.
 * 
 * Ajout par rapport à la classe mère : si aucune base de données ou table n'existe,
 * l'authentification ne plante pas (i.e. renvoit false).
 *
 * @author Bertrand GAUTHIER <bertrand.gauthier@unicaen.fr>
 */
abstract class AbstractDb extends AbstractAdapter
{
    use ModuleOptionsAwareTrait;

    /**
     * @var string
     */
    protected $type;

    /**
     * @var AdapterChainEvent
     */
    protected $event;

    /**
     * @var UserMapperInterface
     */
    protected $mapper;

    /**
     * @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().
        $this->event = $e->getTarget();

        if ($this->event->getIdentity()) {
            return true;
        }

        if ($this->isSatisfied()) {
            $storage = $this->getStorage()->read();
            $this->event
                ->setIdentity($storage['identity'])
                ->setCode(AuthenticationResult::SUCCESS)
                ->setMessages(array('Authentication successful.'));
            return true;
        }

        $userObject = $this->fetchUserObject();
        if ($userObject === null) {
            return false;
        }

        if ($this->moduleOptions->getEnableUserState()) {
            // Don't allow user to login if state is not in allowed list
            if (!in_array($userObject->getState(), $this->moduleOptions->getAllowedLoginStates())) {
                $this->event
                    ->setCode(AuthenticationResult::FAILURE_UNCATEGORIZED)
                    ->setMessages(["Ce compte utilisateur a été désactivé"]);
                $this->setSatisfied(false);
                return false;
            }
        }

        $result = $this->authenticateUserObject($userObject);
        if ($result === false) {
            return false;
        }

        // regen the id
        $session = new SessionContainer($this->getStorage()->getNamespace());
        $session->getManager()->regenerateId();

        // Success!
        $identity = $this->createSessionIdentity($userObject->getUsername());
        $this->event->setIdentity($identity);
        $this->setSatisfied(true);
        $storage = $this->getStorage()->read();
        $storage['identity'] = $this->event->getIdentity();
        $this->getStorage()->write($storage);
        $this->event
            ->setCode(AuthenticationResult::SUCCESS)
            ->setMessages(array('Authentication successful.'));

        return true;
    }

    /**
     * @return \ZfcUser\Entity\UserInterface|null
     */
    abstract protected function fetchUserObject(): ?UserInterface;

    /**
     * @param \ZfcUser\Entity\UserInterface $userObject
     * @return bool
     */
    abstract protected function authenticateUserObject(UserInterface $userObject): bool;

    /**
     * setMapper
     *
     * @param UserMapperInterface $mapper
     * @return self
     */
    public function setMapper(UserMapperInterface $mapper): self
    {
        $this->mapper = $mapper;

        return $this;
    }
}
 No newline at end of file
+7 −6
Original line number Diff line number Diff line
<?php

namespace UnicaenAuth\Authentication\Adapter;

use Interop\Container\ContainerInterface;
@@ -7,19 +8,19 @@ use ZfcUser\Options\ModuleOptions;

class AdapterChainServiceFactory
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null): AdapterChain
    {
        $chain = new AdapterChain();

        $options = $this->getOptions($container);
        $enabledTypes = array_keys($options->getEnabledAuthTypes()); // types d'auth activés

        //iterate and attach multiple adapters and events if offered
        // on attache chaque adapter uniquement s'il est activé
        foreach ($options->getAuthAdapters() as $priority => $adapterName) {
            /** @var AbstractAdapter $adapter */
            $adapter = $container->get($adapterName);
            if (in_array($adapter->getType(), $enabledTypes)) {
                $adapter->attach($chain->getEventManager());
                $adapter->attach($chain->getEventManager(), $priority);
            }
        }

@@ -35,9 +36,9 @@ class AdapterChainServiceFactory
     * set options
     *
     * @param ModuleOptions $options
     * @return AdapterChainServiceFactory
     * @return self
     */
    public function setOptions(ModuleOptions $options)
    public function setOptions(ModuleOptions $options): self
    {
        $this->options = $options;
        return $this;
@@ -49,7 +50,7 @@ class AdapterChainServiceFactory
     * @param ContainerInterface|null $container (optional) Service Locator
     * @return ModuleOptions $options
     */
    public function getOptions(ContainerInterface $container = null)
    public function getOptions(ContainerInterface $container = null): ModuleOptions
    {
        if (!$this->options) {
            if (!$container) {
+0 −28
Original line number Diff line number Diff line
@@ -98,10 +98,6 @@ class Cas extends AbstractAdapter
            return true;
        }

        if (! $this->isEnabled()) {
            return false;
        }

        error_reporting($oldErrorReporting = error_reporting() & ~E_NOTICE);

        $this->getCasClient()->forceAuthentication();
@@ -131,23 +127,6 @@ class Cas extends AbstractAdapter
        return true;
    }

    /**
     * @return bool
     */
    protected function isEnabled(): bool
    {
        $config = $this->moduleOptions->getCas();

        if (! $config) {
            return false;
        }
        if (isset($config['enabled'])) {
            return (bool) $config['enabled'];
        }

        return true;
    }

    /**
     * @inheritDoc
     */
@@ -155,10 +134,6 @@ class Cas extends AbstractAdapter
    {
        parent::logout($e);

        if (! $this->isEnabled()) {
            return;
        }

        $storage = $this->getStorage()->read();
        if (! isset($storage['identity'])) {
            return;
@@ -247,9 +222,6 @@ class Cas extends AbstractAdapter
     */
    public function reconfigureRoutesForCasAuth(RouteInterface $router)
    {
        if (! $this->isEnabled()) {
            return;
        }
        if(!$router instanceof RouteStackInterface) {
            return;
        }
Loading