IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Symfony PHP Discussion :

Symfony Guard Authenticator


Sujet :

Symfony PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Femme Profil pro
    Étudiant
    Inscrit en
    Mai 2017
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2017
    Messages : 87
    Par défaut Symfony Guard Authenticator
    Bonjour,
    J'aurai besoin d'aide pour mettre en place un guard authenticator. J'ai suivi la documentation de symfony mais j'ai un peu de mal. Mon but c'est d'utiliser un ChainProvider pour l'authentification sur mon site web, un utilisateur peut se connecter via LDAP ou via la BDD. J'ai mis en place la connexion LDAP, elle marche parfaitement, mais je n'arrive pas à lier la connexion BDD. Ce que je voudrais c'est que sur le même formulaire de login, Symfony vérifie LDAP puis BDD. Voici mon code pour l'instant
    security.yaml
    Code yaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    security:
        providers:
            chain_provider:
                chain:
                    providers: [intranet_ldap, from_database]
            from_database:
                entity:
                    class: App\Entity\User
                    property: username
            fos_userbundle:
                id: fos_user.user_provider.username
            intranet_ldap:
                id: App\Security\LdapUserProvider
     
        firewalls:
            dev:
                pattern: ^/(_(profiler|wdt)|css|images|js)/
                security: false
            admin:
                pattern:            /admin(.*)
                context:            user
                form_login:
                    provider:       fos_userbundle
                    login_path:     /admin/login
                    use_forward:    false
                    check_path:     /admin/login_check
                    failure_path:   null
                logout:
                    path:           /admin/logout
                    target:         /admin/login
                anonymous:          true
                #switch_user: true
            main:
                guard:
                    authenticators:
                        - App\Security\TokenAuthenticator
                provider:       chain_provider
                pattern:            ^/
                context:            user
                anonymous:          true
                form_login_ldap:
                    service:        Symfony\Component\Ldap\Ldap
                    login_path:     /login
                    check_path:     /login_check
                    dn_string:      'DC=xxx, DC=lan'
                    query_string:   '(&(sAMAccountName={username}))'
                    use_forward:    false
                    always_use_default_target_path: true
                    default_target_path: /profile
                    use_referer:    true
                logout:
                    path:  /logout
                    target: /
     
     
        access_control:
            - { path: ^/efconnect, role: ROLE_USER }
            - { path: ^/elfinder, role: ROLE_USER }
            - { path: ^/profile/, role: ROLE_USER }
            # URL of FOSUserBundle which need to be available to anonymous users
            - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
            #- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/logout, role: IS_AUTHENTICATED_ANONYMOUSLY }
     
            # Admin login page needs to be accessed without credential
            - { path: ^/admin/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/admin/logout$, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/admin/login_check$, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/admin/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
     
            - { path: ^/admin/, role: [ROLE_ADMIN, ROLE_SONATA_ADMIN] }
            - { path: ^/efconnect, role: ROLE_USER }
            - { path: ^/elfinder, role: ROLE_USER }
            - { path: ^/blog/post/create$, role: ROLE_USER }
            - { path: ^/blog/post/edit, role: ROLE_USER }
            - { path: ^/blog/post/delete, role: ROLE_USER }
            - { path: ^/organigrammes/candidats, role: [ROLE_ALGAM_INTRANET_ADMIN_MEMBRE_STAFF, ROLE_SUPER_ADMIN] }
            - { path: ^/.*, role: IS_AUTHENTICATED_ANONYMOUSLY }
        role_hierarchy:
            ROLE_ADMIN:       ROLE_USER
            ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_SONATA_ADMIN, ROLE_ALLOWED_TO_SWITCH]
     
     
        encoders:
            FOS\UserBundle\Model\UserInterface: sha512
     
    acl:
        connection: default
    TokenAuthenticator.php
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    <?php
     
     
    namespace App\Security;
     
     
    use Symfony\Component\HttpFoundation\JsonResponse;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
    use Symfony\Component\Security\Core\Exception\AuthenticationException;
    use Symfony\Component\Security\Core\User\UserInterface;
    use Symfony\Component\Security\Core\User\UserProviderInterface;
    use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
     
    class TokenAuthenticator extends AbstractGuardAuthenticator
    {
     
        public function start(Request $request, AuthenticationException $authException = null)
        {
            $data = array(
                'message' => 'Authentification requise'
            );
     
            return new JsonResponse($data, Response::HTTP_UNAUTHORIZED);
        }
     
        public function supports(Request $request)
        {
            return $request->headers->has('X-AUTH-TOKEN');
        }
     
        public function getCredentials(Request $request)
        {
            return array(
                'token' => $request->headers->get('X-AUTH-TOKEN'),
            );
        }
     
        public function getUser($credentials, UserProviderInterface $userProvider)
        {
            $apiKey = $credentials['token'];
     
            if(null === $apiKey){
                return;
            }
     
            return $userProvider->loadUserByUsername($credentials['username']);
        }
     
        public function checkCredentials($credentials, UserInterface $user)
        {
            // TODO: Implement checkCredentials() method.
        }
     
        public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
        {
            $data = array(
                'message' => strtr($exception->getMessageKey(), $exception->getMessageData())
            );
     
            return new JsonResponse($data, Response::HTTP_FORBIDDEN);
        }
     
        public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
        {
            return null;
        }
     
        public function supportsRememberMe()
        {
            return false;
        }
    }
    J'ai aussi dans mon rep Securirty LdapUser.php et LdapUserProvider.php mais je ne pense pas que ce soit utile donc je ne les fournis pas pour le moment. Est-ce que je dois créé un UserProvider pour la BDD aussi?
    Quelqu'un pourrait m'aider pour mettre en place la connexion avec la BDD en parallèle avec le LDAP? Je suis vraiment bloquée et je n'arrive pas à adapter les exemples que je trouve sur le net. Merci d'avance!

  2. #2
    Membre chevronné
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2011
    Messages
    351
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2011
    Messages : 351
    Par défaut
    Salut,

    Citation Envoyé par Akame14 Voir le message
    Ce que je voudrais c'est que sur le même formulaire de login, Symfony vérifie LDAP puis BDD.
    Tu voudrais que ce soit toujours "LDAP + BDD" (pour être authentifié, l'utilisateur devrait se trouver dans le LDAP ET dans la BDD), ou alors que l'authentification "BDD" soit une fallback utilisée uniquement quand l'authentification LDAP a échoué ?

    Quelle version de Symfony utilises-tu ? Visiblement le support des Authenticator dans le composant LDAP est récent (Symfony 5.1 https://github.com/symfony/ldap/comm...41f1751b405e45) et il utilise le nouveau système d'authentification qui est encore "experimental" dans la 5.1 (cf. https://symfony.com/doc/current/secu...nticators.html).

    Actuellement quand tu authentifies un utilisateur via LDAP, ton App\Security\TokenAuthenticator est exécuté ? Ou bien c'est uniquement Symfony\Component\Ldap\Ldap qui fait son job et redirige vers /profile ?

  3. #3
    Membre confirmé
    Femme Profil pro
    Étudiant
    Inscrit en
    Mai 2017
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2017
    Messages : 87
    Par défaut
    Bonjour, merci de votre réponse.
    Pardon, je n'ai aps été claire dans mes explications. Je voudrais que ce soit un fallback, on teste le LDAP et si l'utilisateur n'est pas présent dedans, on va alors tester en BDD.

    Ma version de Symfony est la 4.4.11. J'ai utilisé Authenticator car je ne voyais pas comment faire autrement et je n'ai pas fait attetion à la version de Symfony

    Quand je clique sur le bouton "Se connecter" le TokenAuthenticator semble bien être appelé. En tout cas on passe bien dans le constructeur, je ne sais pas trop comment vérifier autrement ^^.

  4. #4
    Membre chevronné
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2011
    Messages
    351
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2011
    Messages : 351
    Par défaut
    Salut,

    À mon avis il faudrait que tu aies deux Guards, le premier qui s'occupe de l'authentification LDAP et le second dédié à l'authentification BDD.
    Sur cette page de la doc tu trouveras comment configurer le composant pour qu'ils partagent le même point d'entrée : https://symfony.com/doc/current/secu...ed-entry-point

    En gros si la méthode supports de ton TokenAuthenticator retourne false, Symfony exécutera le second Guard paramétré, donc celui dédié à la BDD dans lequel tu auras implémenté ta logique. (si besoin le rôle de chaque méthode est détaillé ici : https://symfony.com/doc/4.4/security...icator-methods).

    Cela dit je pense que cette solution ne colle pas tout à faire à ton besoin, car il faudrait être capable de distinguer si une requête concerne une authentification via LDAP ou via BDD (dès la méthode supports). Or toi tu voudrais avoir un système de fallback qui exécute le second Guard lorsque le premier échoue (càd quand on atteint sa méthode onAuthenticationFailure) et ça... je vois pas trop comment faire pour l'instant^^

    Aussi je me pose des questions sur ton code, car dans ton TokenAuthenticator, tu récupères la valeur d'un header (X-AUTH-TOKEN) quand elle existe, mais finalement tu charges l'utilisateur uniquement à partir du username de la requête (sans jamais te servir de la valeur du X-AUTH-TOKEN) :
    • Est-ce normal que ton TokenAuthenticator fonctionne ainsi ?
    • Qui définit la valeur du X-AUTH-TOKEN ?
    • Est-ce que tu es certaine que l'authentification LDAP est fonctionnelle ?

  5. #5
    Membre confirmé
    Femme Profil pro
    Étudiant
    Inscrit en
    Mai 2017
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2017
    Messages : 87
    Par défaut
    Merci pour tes réponses. Pour tout te dire, j'avance un peu à l'aveugle donc je tente des choses sans vraiment savoir à quoi elles correspondent. On m'a conseillé d'utiliser le GuardAuthenticator et j'ai cherché des exemples sur Internet et je les ai copiés collés en essayant d'adapter un peu mais je ne suis absolument pas sûre de ce que j'ai fait, c'est pour cela que je viens demander de l'aide.
    Pour ce qui est du LDAP, oui je suis sûre que l'authentification est fonctionnelle

  6. #6
    Membre chevronné
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2011
    Messages
    351
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2011
    Messages : 351
    Par défaut
    On passe tous par là quand on découvre, t'inquiète pas^^

    Je vais essayer de t'expliquer dans les grandes lignes comment fonctionne le composant Security dans Symfony (sachant que je peux me tromper, avoir mal compris et/ou trop simplifier un point, donc toute correction est la bienvenue). Grosso modo Symfony a besoin de deux choses :

    1. Un "user provider", très souvent ça sera ton entité User. Tu peux lire cette page de la doc qui détaille à quoi sert un "user provider", liste ceux existants de base dans le composant Securty, et explique comment configurer ce dernier (a minima pour spécifier quel "user provider" on veut utiliser).

    2. Un "authentication provider", on peut se le représenter comme "du code qui va s'exécuter automatiquement AVANT le code du contrôleur qu'on va associer à l'authentification dans la config. De base il y en a plusieurs qui correspondent à des cas d'utilisation standards (formulaire de login, ldap, etc.), facile à mettre en place mais pas toujours évident à personnaliser ensuite (cf. https://symfony.com/doc/4.4/security...providers.html).


    Si tu parcoures la doc, tu verras qu'à de nombreux endroits il est recommandé de ne plus utiliser ces "authentication providers" de base mais à la place de créer et d'utiliser son propre "Guard authenticator". Un Guard est une classe qui va te permettre de contrôler, étape par étape, ce que faisait un peu "magiquement" les "authentication providers" de base. Pour saisir la différence entre les deux systèmes (et si ça t'intéresse, que tu as le temps, etc.), tu peux comparer cette page qui détaille comment mettre en place un Guard authenticator pour gérer l'authentification via un formulaire "username/password" standard, avec cette page qui explique comment "faire la même chose" mais en utilisant le provider "form_login" (ce qui n'est plus recommandé). Dernier point, un Guard doit contenir impérativement certaines méthodes qui sont appelées chacune à leur tour (selon le résultat de la méthode précédente), cette page détaille le rôle de chaque méthode (c'est important de comprendre ça car quand tu crées un Guard, c'est à toi t'implémenter ta logique d'authentification dans ces méthodes).


    Bref, assez de blabla conceptuel, mais ça va permettre de faire le lien avec ta situation : actuellement tu utilises un des "built-in authentication providers" (https://symfony.com/doc/4.4/security/ldap.html), le problème c'est qu'il est plutôt difficile de personnaliser son comportement (c'est le reproche principal de ces providers de base dès qu'on sort des cas d'utilisation standards). Tu as aussi un custom Guard appelé "TokenAuthenticator" mais qui à mon avis est mal nommé (car tu ne veux pas t'authentifier via un token), je pense que la doc (qui n'est pas du tout limpide sur ces parties) t'as induite en erreur.

    À ta place pour faire les choses bien (càd utiliser uniquement un Guard custom dans lequel on aura toute la logique "LDAP" et "BDD") :

    1. Je repartirai de zéro (désolé), càd faire le ménage dans la config de Security, supprimer le TokenAuthenticator, etc... histoire de pas être pollué par les différentes tentatives précédentes
    2. Je suivrai point par point cette page : https://symfony.com/doc/4.4/security...gin_setup.html (hésite pas à regarder le code des fichiers générés par les commandes "make")
    3. Normalement arrivée ici, tu auras une authentification "BDD" (formulaire, login/password, qui récupère le User dans la BDD) fonctionnelle et surtout réalisée par un Guard custom (donc plus facilement modifiable)
    4. Arrivée là, il te restera à modifier à nouveau les méthodes de ton Guard custom pour y implémenter la partie "authentification LDAP" (qui peut vite être complexe)


    À propos du dernier point, j'ai trouvé ça (attention c'est du Symfony 3) qui exprime un besoin similaire au tien : https://stackoverflow.com/questions/...eckcredentials
    Vu que j'ai toujours galéré le peu de fois où j'ai utilisé LDAP, je te promets rien, mais visiblement pour implémenter dans ton Guard la logique du "ldap provider", ça pourra se faire assez simplement (un peu de config puis en injectant le service du composant, à voir à l'utilisation si c'est suffisant ou pas).

    Bonne lecture, si tu te lances dans le grand chantier, bon courage et surtout persévère mais n'hésite pas à poser des questions si besoin.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 27/03/2020, 13h02
  2. [3.x] Utiliser guard Symfony avec multiple provider
    Par Wilhem31 dans le forum Symfony
    Réponses: 1
    Dernier message: 11/09/2018, 11h43
  3. [Securité] Différence entre Impersonation et Authentication?
    Par Laurent Dardenne dans le forum Windows
    Réponses: 6
    Dernier message: 13/08/2009, 11h32
  4. Body...guard
    Par Sylvain James dans le forum XMLRAD
    Réponses: 4
    Dernier message: 11/03/2005, 15h07
  5. Mise en place d'une solution Data Guard 9i R2
    Par user_oracle dans le forum Oracle
    Réponses: 4
    Dernier message: 16/02/2005, 10h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo