Symfony2 : gérer l’identification utilisateur LDAP

Logo SymfonyIl est possible avec Symfony2 d’authentifier l’utilisateur LDAP.
Pour cela il faut créer une première classe UserProvider qui sera le fournisseur d’utilisateur, et une seconde classe User qui sera notre utilisateur.
Cette article détaillé en explique le fonctionnement : http://symfony.com/fr/doc/current/cookbook/security/custom_provider.html

Tout d’abord, on va renseigner dans le fichier app/config/security.yml la façon dont on va authentifié l’utilisateur.

security:
    providers:
        ldap:
            id: user_provider

    firewalls:
        secured_area:
            pattern: ^/
            remote_user:
                provider: ldap

On va retrouver la clef « user_provider » dans notre fichier de déclaration des services app/config/services.yml

services:
    ad:
        class: AppBundleUtilsAd
        arguments: ["%ad_host%", "%ad_user%", "%ad_password%"]
    user_provider:
        class: AppBundleSecurityUserProvider
        calls:
            - [setAd, ["@ad"]]

Le service « ad » est une classe qui me permet d’aller chercher les informations utilisateur dans l’Active Directory (nom, prénom, description etc.), c’est pourquoi je l’injecte dans ma classe UserProvider.

Voici le contenu des classes UserProvider et User :

namespace AppBundle\Security;

use AppBundle\Utils\Ad;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\UserProviderInterface;

class UserProvider implements UserProviderInterface
{
    private $ad;

    /**
     * @param string $username
     * @return UserInterface
     * @throws UsernameNotFoundException
     */
    public function loadUserByUsername($username)
    {
        if ($userAd = $this->getAd()->getUserByLogin($username)) {
            return new User($userAd->samaccountname, $userAd);
        }

        throw new UsernameNotFoundException('Utilisateur "' . $username . '" introuvable');
    }

    /**
     * @param UserInterface $user
     * @return UserInterface
     * @throws UnsupportedUserException
     */
    public function refreshUser(UserInterface $user)
    {
        if (!$user instanceof User) {
            throw new UnsupportedUserException('Instance "' . get_class($user) . '" non supportée');
        }

        return $this->loadUserByUsername($user->getUsername());
    }

    /**
     * @param string $class
     * @return bool
     */
    public function supportsClass($class)
    {
        return $class === 'AppBundle\Security\User';
    }

    /**
     * @param Ad $ad
     * @return void
     */
    public function setAd(Ad $ad)
    {
        $this->ad = $ad;
    }

    /**
     * @return Ad $ad
     */
    public function getAd()
    {
        return $this->ad;
    }
}
namespace AppBundle\Security;

use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Role\Role;
use AppBundle\Utils\UserAd;

class User implements UserInterface
{
    private $username;
    private $password;
    private $roles = array();
    private $nom;
    private $prenom;
    private $description;

    /**
     * @param string $username
     * @param UserAd $userAd
     * @return User
     */
    public function __construct($username, UserAd $userAd)
    {
        $this->username = $username;
        $this->nom = $userAd->sn;
        $this->prenom = $userAd->givenname;
        $this->description = $userAd->description;

        // établit les rôles
        $roles = array('ROLE_USER');

        if ($this->getUsername() === 'jdoe') {
            $roles[] = 'ROLE_SUPER_ADMIN';
        }

        $this->setRoles($roles);
    }

    /**
     * @return string
     */
    public function getUsername()
    {
        return $this->username;
    }

    /**
     * @return string
     */
    public function getPassword()
    {
        return $this->password;
    }

    /**
     * @return Role[] The user roles
     */
    public function getRoles()
    {
        $roles = $this->roles;

        if (empty($roles)) {
            $roles[] = 'ROLE_USER';
        }

        return array_unique($roles);
    }

    /**
     * @param array
     * @return void
     */
    public function setRoles(array $roles)
    {
        $this->roles = $roles;
    }

    /**
     * @return void
     */
    public function getSalt()
    {
        return;
    }

    /**
     * @return void
     */
    public function eraseCredentials()
    {
    }

    /**
     * @return string
     */
    public function getNom()
    {
        return $this->nom;
    }

    /**
     * @return string
     */
    public function getPrenom()
    {
        return $this->prenom;
    }

    /**
     * @return string
     */
    public function getDescription()
    {
        return $this->description;
    }
}

Ces deux classes doivent impérativement définir les méthodes des interfaces UserProviderInterface et User.

Cet exemple est à adapté selon votre système LDAP.

Le fichier de log access.log d’Apache affichera le login AD de la personne qui lance l’appel HTTP, cela peut vous permettre d’isoler ce champ dans un dashboard Kibana.

Share Button

Laisser un commentaire.

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.