Chapitre 10.5 — OAuth & connexion sociale
Partie 10 : Sécurité — Chapitre 5/6 Version de référence : Symfony 7.4 / oauth2-client-bundle.
⏱️ TL;DR
- OAuth2 (flux authorization code) permet de se connecter via un tiers (Google, GitHub…) sans gérer de mot de passe : l’utilisateur s’authentifie chez le fournisseur, qui renvoie un code, échangé contre un access token, puis on récupère son profil.
- On utilise
knpuniversity/oauth2-client-bundle+ un client (league/oauth2-google,-github…), configuré avec unclient_id/client_secret(obtenus chez le fournisseur).- Un authenticator OAuth (
OAuth2Authenticator) charge/crée leUserlocal à partir du profil renvoyé.- Points de sécurité : le paramètre
state(anti-CSRF du flux), la vérification de l’email, et le rattachement à un compte existant.- Pour un dev Next.js : c’est le « Login with Google/GitHub » que vous connaissez (façon NextAuth) — mais côté Symfony, qui reste la source de vérité des comptes.
🎯 Objectifs
- Comprendre le flux OAuth2 authorization code.
- Configurer un client OAuth (ex. GitHub).
- Charger/créer un utilisateur local depuis le profil.
- Connaître les précautions de sécurité.
1. Le flux OAuth2 (authorization code)
L’idée : jamais le mot de passe ne transite par vous. Le fournisseur atteste l’identité ; vous récupérez un profil et gérez le compte local.
2. Installer et configurer
composer require knpuniversity/oauth2-client-bundle league/oauth2-githubOn enregistre l’application chez le fournisseur (GitHub → Developer settings → OAuth Apps) pour obtenir un client_id et un client_secret, et on déclare l’URL de callback (https://booklab.test/connect/github/check).
# config/packages/knpu_oauth2_client.yaml
knpu_oauth2_client:
clients:
github:
type: github
client_id: '%env(OAUTH_GITHUB_ID)%'
client_secret: '%env(OAUTH_GITHUB_SECRET)%'
redirect_route: connect_github_checkLe client_secret est un secret (coffre de secrets, chapitre 3.4).
3. Le contrôleur de connexion
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
final class GithubController extends AbstractController
{
#[Route('/connect/github', name: 'connect_github')]
public function connect(ClientRegistry $clientRegistry): Response
{
return $clientRegistry->getClient('github')
->redirect(['user:email'], []); // scopes demandés
}
#[Route('/connect/github/check', name: 'connect_github_check')]
public function check(): void
{
// interceptée par l'authenticator OAuth (ci-dessous)
}
}4. L’authenticator OAuth
Un authenticator (chapitre 10.1) transforme le profil GitHub en User local :
use KnpU\OAuth2ClientBundle\Security\Authenticator\OAuth2Authenticator;
final class GithubAuthenticator extends OAuth2Authenticator
{
public function authenticate(Request $request): Passport
{
$client = $this->clientRegistry->getClient('github');
$accessToken = $this->fetchAccessToken($client);
return new SelfValidatingPassport(
new UserBadge($accessToken->getToken(), function () use ($accessToken, $client) {
$githubUser = $client->fetchUserFromToken($accessToken);
$email = $githubUser->getEmail();
// trouver le User local par email, ou le créer
return $this->userRepository->findOneBy(['email' => $email])
?? $this->createUserFromGithub($githubUser);
})
);
}
// onAuthenticationSuccess / Failure ...
}Le point clé : à partir du profil, on retrouve l’utilisateur local (par email) ou on le crée. C’est là que Symfony reste la source de vérité des comptes.
5. Précautions de sécurité
- Le paramètre
state: un jeton anti-CSRF du flux OAuth, géré par le bundle. Il empêche qu’un attaquant force un callback. Ne le désactivez pas. - Vérification de l’email : certains fournisseurs renvoient un email non vérifié. Si vous rattachez des comptes par email, exigez un email vérifié côté fournisseur (ou vérifiez-le vous-même), sinon un attaquant pourrait usurper un compte.
- Rattachement de comptes : gérez le cas « cet email existe déjà avec un mot de passe » — proposez de lier le compte social au compte existant plutôt que d’en créer un doublon.
- Scopes minimaux : ne demandez que les permissions nécessaires (
user:email), pas plus.
⚠️ Piège usurpation par email : rattacher automatiquement un login social à un compte local du même email est dangereux si l’email du fournisseur n’est pas vérifié : quelqu’un pourrait créer un compte GitHub avec l’email de votre victime et « devenir » elle. Exigez un email vérifié, et pour lier à un compte existant protégé, demandez une confirmation (ou une connexion préalable).
💡 Pour un dev Next.js : si vous avez utilisé NextAuth/Auth.js, le concept est identique (providers OAuth, callback, session). Ici, c’est Symfony qui orchestre et qui possède les comptes (dans sa base). Pour un front Next.js sur l’API, vous pouvez faire porter le flux OAuth par Symfony (puis émettre un JWT) ou par Next.js (puis échanger contre un JWT Symfony) — au choix selon l’architecture ; l’important est une source de vérité des comptes.
✏️ Exercices
Exercice 1. Résumez les étapes du flux authorization code pour « Se connecter avec GitHub ».
✅ Solution
- L’utilisateur clique → Symfony redirige vers GitHub (avec
client_id, scopes,state). 2. L’utilisateur s’authentifie et autorise chez GitHub. 3. GitHub redirige vers/connect/github/check?code=...&state=.... 4. Symfony échange lecodecontre un access token. 5. Symfony récupère le profil (email, etc.). 6. Il trouve ou crée leUserlocal et ouvre la session. Le mot de passe ne transite jamais par Symfony.
Exercice 2. Pourquoi le paramètre state est-il important ?
✅ Solution
C’est un jeton anti-CSRF du flux OAuth : Symfony le génère au départ et le vérifie au callback. Il garantit que la réponse du fournisseur correspond bien à une demande initiée par l’utilisateur, empêchant un attaquant de forger un callback (injection de code/token). Le bundle le gère automatiquement — à ne pas désactiver.
Exercice 3. Quel risque à rattacher un login social à un compte local par email, et comment l’éviter ?
✅ Solution
Risque d’usurpation si l’email du fournisseur n’est pas vérifié : un attaquant crée un compte social avec l’email de la victime et « hérite » du compte local. On l’évite en exigeant un email vérifié côté fournisseur, et pour lier à un compte existant protégé, en demandant une confirmation explicite (ou une connexion préalable au compte local).
🧠 Quiz de révision
1. Que permet OAuth2 en une phrase ?
Se connecter via un tiers (Google/GitHub) sans gérer de mot de passe : le fournisseur atteste l’identité, on récupère le profil et on gère le compte local.
2. Que reçoit-on au callback, et qu’en fait-on ?
Un code d’autorisation, qu’on échange contre un access token, lequel permet de récupérer le profil de l’utilisateur.
3. Rôle de l’authenticator OAuth ?
Transformer le profil du fournisseur en User local : le retrouver (par email) ou le créer, puis authentifier.
4. À quoi sert le paramètre state ?
state ?C’est l’anti-CSRF du flux OAuth : il garantit que le callback correspond à une demande initiée par l’utilisateur.
5. Quelle précaution avant de rattacher un compte social par email ?
Exiger un email vérifié (et confirmer le rattachement à un compte existant), pour éviter l’usurpation via un email non vérifié.
Prochain chapitre : 10.6 — 2FA & durcissement — double authentification, rate limiting et checklist OWASP.