480 mots
2 minutes
Authentification avec Facebook dans Symfony 6

Dans un précédent article, j’avais déjà évoqué ce sujet en prenant comme exemple une authentification Google. Nous allons aujourd’hui faire de même avec Facebook. (Le plus compliqué est souvent de récupérer les clés API Facebook.)


Un des intérêts de se connecter à l’aide du compte Facebook est d’éviter à l’utilisateur de saisir un énième mot de passe.

Création du projet Symfony#

Comme d’habitude, nous allons partir de zéro et commencer par créer le projet :

symfony new sffacebook

Ajoutons ensuite toutes les librairies nécessaires :

composer req twig
composer req --dev symfony/maker-bundle
composer req security
composer req orm
composer req --dev debug

Et en particulier celles qui nous permettront d’utiliser Facebook pour l’authentification :

composer require knpuniversity/oauth2-client-bundle
composer require league/oauth2-facebook

Configuration Facebook#

Nous allons d’abord récupérer nos clés Facebook. Pour cela, connectez-vous au portail développeur Facebook, puis dans le menu, allez sur “Mes applications” et cliquez sur “Créer une app”.

Choisissez “Aucun” comme type d’application :

Choix du type d'application

Saisissez ensuite le nom de votre application (par exemple, SymfonyAuth) sans utiliser de mots réservés comme “Facebook” ou “FB”.

Ajoutez ensuite le produit “Facebook Login” :

Ajout du produit Facebook Login

Dans le menu de gauche, sous “Facebook Login”, cliquez sur “Paramètres” et configurez les URL de redirection OAuth valides (par exemple, https://votre-domaine/connect/facebook/check) :

Configuration des URL de redirection

Enfin, allez dans “Paramètres -> Général” et récupérez votre identifiant d’application ainsi que la clé secrète. Ajoutez-les dans le fichier .env.local :

OAUTH_FACEBOOK_CLIENT_ID=app_id
OAUTH_FACEBOOK_CLIENT_SECRET=app_secret

Création de l’entité User#

Utilisez le MakerBundle pour créer l’entité User :

bin/console make:entity

Ajoutez ensuite les colonnes nécessaires et migrez la base de données :

bin/console make:migration
bin/console doctrine:migration:migrate

Configuration de l’authentification#

Dans le fichier config/packages/knpu_oauth2_client.yaml :

knpu_oauth2_client:
    clients:
        facebook:
            type: facebook
            client_id: '%env(OAUTH_FACEBOOK_CLIENT_ID)%'
            client_secret: '%env(OAUTH_FACEBOOK_CLIENT_SECRET)%'
            redirect_route: connect_facebook_check
            graph_api_version: v2.12

Création d’un contrôleur#

Créez un contrôleur pour gérer la connexion/déconnexion et l’authentification via Facebook :

<?php

namespace App\Controller;

use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;

class FacebookController extends AbstractController
{
    #[Route('/connect/facebook', name: 'connect_facebook')]
    public function connectAction(ClientRegistry $clientRegistry): RedirectResponse
    {
        return $clientRegistry->getClient('facebook')->redirect(['public_profile', 'email'], []);
    }

    #[Route('/connect/facebook/check', name: 'connect_facebook_check')]
    public function connectCheckAction(Request $request)
    {
        // Gestion après authentification
    }
}

Ajoutez un bouton de connexion dans votre template Twig (facebook/index.html.twig) :

<a href="{{ path('connect_facebook') }}">
    <img src="/facebooklogo.png" alt="Se connecter avec Facebook">
</a>

Mise en place d’un GuardAuthenticator#

Créez un GuardAuthenticator pour gérer l’authentification utilisateur :

<?php
namespace App\Security;

use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use KnpU\OAuth2ClientBundle\Security\Authenticator\OAuth2Authenticator;
use League\OAuth2\Client\Provider\FacebookUser;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;

class FacebookAuthenticator extends OAuth2Authenticator
{
    public function __construct(
        private ClientRegistry $clientRegistry,
        private EntityManagerInterface $entityManager,
        private RouterInterface $router
    ) {}

    public function authenticate(Request $request): Passport
    {
        $client = $this->clientRegistry->getClient('facebook');
        $accessToken = $this->fetchAccessToken($client);

        return new SelfValidatingPassport(
            new UserBadge($accessToken->getToken(), function () use ($client, $accessToken) {
                $facebookUser = $client->fetchUserFromToken($accessToken);
                $email = $facebookUser->getEmail();

                $existingUser = $this->entityManager->getRepository(User::class)->findOneBy(['email' => $email]);
                if (!$existingUser) {
                    $existingUser = new User();
                    $existingUser->setEmail($email);
                    $this->entityManager->persist($existingUser);
                }
                $this->entityManager->flush();

                return $existingUser;
            })
        );
    }
}

Configurez le security.yaml pour utiliser le GuardAuthenticator :

firewalls:
    main:
        custom_authenticators:
            - App\Security\FacebookAuthenticator

Conclusion#

Vous pouvez désormais vous connecter à votre site via Facebook. Pour vous déconnecter, rendez-vous sur /logout.

Le code complet est disponible sur GitHub : https://github.com/gponty/sffacebook