---
title: 'Ajouter Google Authenticator à une connexion Symfony'
description: 'Configure SchebTwoFactorBundle, ajoute un secret Google Authenticator au compte et vérifie que les routes protégées attendent le second facteur.'
pubDate: 2023-09-15
family: 'api-donnees'
tags: []
heroImage: /images/authentification-a-deux-facteurs-avec-google-authenticator.webp
videoUrl: 'https://youtu.be/mQ2ouZJhsVk'
updatedDate: 2026-10-13
---

Ajouter Google Authenticator ne consiste pas seulement à afficher un QR code. Ton application doit conserver un secret partagé, interrompre la connexion après le mot de passe et refuser l'accès aux pages protégées tant que le code n'est pas validé.[12][13]

La vidéo associée présente Symfony 6 en 2023. Ce guide décrit désormais **Symfony 7.4 et SchebTwoFactorBundle 8**, une combinaison couverte par la documentation officielle.[12] Les fragments suivants sont documentés, mais le parcours complet avec une base de données et un téléphone n'a pas été exécuté pour cet article.

## 1. Vérifier les prérequis de la connexion

Pars d'une application dont la connexion par mot de passe fonctionne déjà : un utilisateur persistant, Symfony Security, Twig, un firewall avec session et des pages protégées. Ce guide ajoute le second facteur ; il ne génère pas toute l'authentification de départ.

Sauvegarde ta configuration et installe les deux paquets :

```bash
composer require 'scheb/2fa-bundle:^8.0' 'scheb/2fa-google-authenticator:^8.0'
composer check-platform-reqs
```

La version 8 du bundle est compatible avec Symfony 7.4 et 8.x.[12] Si ton application reste sur Symfony 6, choisis la documentation et la version de bundle correspondantes plutôt que de forcer ces contraintes.

## 2. Ajouter le secret à ton utilisateur

Ton entité doit implémenter `Scheb\TwoFactorBundle\Model\Google\TwoFactorInterface`. Ajoute ces membres à ton entité existante, en conservant ses interfaces et méthodes Symfony :

```php
#[ORM\Column(type: 'string', nullable: true)]
private ?string $googleAuthenticatorSecret = null;

public function isGoogleAuthenticatorEnabled(): bool
{
    return null !== $this->googleAuthenticatorSecret;
}

public function getGoogleAuthenticatorUsername(): ?string
{
    return $this->getUserIdentifier();
}

public function getGoogleAuthenticatorSecret(): ?string
{
    return $this->googleAuthenticatorSecret;
}

public function setGoogleAuthenticatorSecret(?string $secret): void
{
    $this->googleAuthenticatorSecret = $secret;
}
```

Cet extrait suppose que `Doctrine\ORM\Mapping` est importé sous l'alias `ORM`. Les méthodes viennent du contrat décrit par le [fournisseur Google du bundle](https://github.com/scheb/2fa/blob/8.x/doc/providers/google.rst).[13] Avec cette implémentation, un secret non nul active le second facteur : ne le persiste pas définitivement avant la confirmation d'enrôlement.

Si tu utilises Doctrine Migrations, génère puis relis la migration avant de l'appliquer :

```bash
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
```

Ces commandes supposent que Doctrine ORM et Migrations sont déjà installés. Si ta persistance est différente, adapte le stockage et consulte le service de persistance attendu par le bundle.[12]

## 3. Activer le fournisseur et les routes

Dans `config/packages/scheb_2fa.yaml` :

```yaml
scheb_two_factor:
  google:
    enabled: true
    issuer: 'Mon application'
```

Dans `config/routes/scheb_2fa.yaml` :

```yaml
2fa_login:
  path: /2fa
  controller: 'scheb_two_factor.form_controller::form'

2fa_login_check:
  path: /2fa_check
```

Le contrôleur fourni affiche le formulaire de saisie. Les deux routes doivent se trouver dans le périmètre du firewall qui gère ta connexion.[12]

## 4. Protéger le passage entre les deux facteurs

Ajoute `two_factor` à ton firewall existant, ici nommé `main`. Ne remplace pas son provider ou son mécanisme de login par cet extrait :

```yaml
security:
  firewalls:
    main:
      two_factor:
        auth_form_path: 2fa_login
        check_path: 2fa_login_check

  access_control:
    - { path: ^/logout, roles: PUBLIC_ACCESS }
    - { path: ^/2fa, roles: IS_AUTHENTICATED_2FA_IN_PROGRESS }
    - { path: ^/login, roles: PUBLIC_ACCESS }
    - { path: ^/compte, roles: ROLE_USER }
```

L'ordre est important : place les règles de déconnexion et de second facteur avant les règles générales.[12] Adapte les chemins à ton application et conserve les protections de tes autres routes. Un firewall sans session n'est pas le périmètre de ce parcours interactif.

## 5. Enrôler le téléphone sans divulguer le secret

Dans une page de paramètres accessible à un utilisateur déjà authentifié, injecte `GoogleAuthenticatorInterface` depuis le namespace `Scheb\TwoFactorBundle\Security\TwoFactor\Provider\Google`. Le service fournit `generateSecret()` et `getQRContent($user)`.[13]

Génère un secret provisoire côté serveur, conserve-le dans la session pendant l'enrôlement et utilise-le sur une copie de l'utilisateur pour construire le contenu QR. Fais scanner ce QR par Google Authenticator. Demande ensuite le code affiché et valide-le avec `checkCode($user, $code)` avant de persister le secret sur le vrai compte.

Le contrôleur d'enrôlement doit vérifier l'utilisateur courant et protéger ses actions contre le CSRF. Il n'est pas fourni ici : son formulaire et sa persistance dépendent de ton application. **Ne présente pas le simple affichage du QR comme une activation terminée.**

Rends le QR dans ton application avec une bibliothèque locale. Le bundle déconseille un service QR externe, car le contenu transmet le secret.[13] Ce secret doit pouvoir être relu pour vérifier les codes : ne le traite pas comme un mot de passe à hacher. Limite l'accès au stockage et prévois sa protection au repos.

## 6. Vérifier le parcours et les cas de panne

Contrôle les configurations puis teste avec un compte dédié :

```bash
php bin/console lint:yaml config/packages/security.yaml config/packages/scheb_2fa.yaml
php bin/console debug:router
```

**Résultat attendu, non observé ici** : après un mot de passe valide, le compte enrôlé passe par `/2fa`. Un mauvais code ne donne pas accès à `/compte`, y compris en ouvrant directement cette URL. Un code valide termine la connexion. Le bouton de déconnexion reste utilisable pendant cette étape.

Si tous les codes sont rejetés, vérifie le secret et la synchronisation des horloges : Google Authenticator utilise des codes à six chiffres renouvelés toutes les trente secondes.[13] Ajoute une limitation des tentatives conformément au [guide anti-brute-force du bundle](https://symfony.com/bundles/SchebTwoFactorBundle/8.x/brute_force_protection.html).[14] Prévois enfin une récupération contrôlée du compte, par exemple avec les codes de secours du bundle, avant de rendre la 2FA obligatoire.[12]

La vidéo associée reste disponible pour son contexte Symfony 6 ; utilise les sources ci-dessous pour cette configuration Symfony 7.4.

## Sources

[12] https://symfony.com/bundles/SchebTwoFactorBundle/8.x/installation.html
[13] https://github.com/scheb/2fa/blob/8.x/doc/providers/google.rst
[14] https://symfony.com/bundles/SchebTwoFactorBundle/8.x/brute_force_protection.html
