Introduction à l'authentification à deux facteurs (2FA)
L'authentification à deux facteurs (2FA) est une méthode de sécurité qui ajoute une couche supplémentaire de protection en demandant à l'utilisateur de fournir, en plus de son mot de passe, un second facteur d'identification. Dans ce cas, il s'agit d'un code généré par une application comme Google Authenticator. L'intérêt est de rendre l'accès aux comptes plus sécurisé même si un mot de passe est compromis.
Dans ce tutoriel, nous allons créer une application PHP qui implémente cette fonctionnalité en utilisant des bibliothèques spécialisées pour générer des codes temporaires (OTP) et des QR codes que l'utilisateur pourra scanner avec son smartphone pour lier son compte à Google Authenticator.
Prérequis
Avant de commencer, vous devez avoir configuré votre environnement PHP. Vous aurez également besoin de Composer, un gestionnaire de dépendances pour PHP qui permet d'ajouter facilement des bibliothèques tierces. Voici les bibliothèques que nous allons utiliser dans ce tutoriel :
- Pragma RX Google2FA : Cette bibliothèque génère des One-Time Passwords (OTP), des codes temporaires utilisés dans l'authentification 2FA.
- Bacon QR Code : Cette bibliothèque permet de générer des QR codes pour que l'utilisateur puisse rapidement configurer l'authentification dans Google Authenticator en scannant ce QR code.
Installer les bibliothèques nécessaires
Pour installer les bibliothèques, ouvrez un terminal dans le répertoire de votre projet PHP et exécutez la commande suivante :
composer require pragmarx/google2fa bacon/bacon-qr-code
Cela va ajouter les bibliothèques à votre projet et mettre à jour votre fichier composer.json
. Cela créera également un fichier autoload.php
qui facilitera le chargement automatique des classes des bibliothèques.
Initialisation de l'application
Dans cette étape, nous allons initialiser notre projet PHP et démarrer une session pour stocker des données utilisateur, telles que la clé secrète générée.
Dans votre fichier index.php
, commencez par inclure l'autoload généré par Composer, et démarrez une session :
require 'vendor/autoload.php';
session_start();
Pourquoi démarrer une session ?
Nous utilisons la session PHP pour stocker des informations temporaires comme la clé secrète de l'utilisateur. Cette clé sera nécessaire pour générer et vérifier les codes OTP.
Ensuite, initialisez Google2FA :
use PragmaRX\Google2FA\Google2FA;
$google2FA = new Google2FA();
Cela permet de préparer la bibliothèque pour générer des OTP et gérer la vérification des codes.
Générer une clé secrète
Chaque utilisateur doit avoir une clé secrète unique qui sera utilisée pour générer les codes OTP. Cette clé doit être stockée quelque part (par exemple dans une base de données), mais ici nous la stockons en session pour cette démo.
// On génère une clé secrète
$secretKey = $google2FA->generateSecretKey();
// On stocke dans une variable $user
$user = [
'google2FA_secret' => $secretKey,
'email' => 'exemple@demo.fr'
];
$_SESSION['user'] = $user;
// On nomme notre app
$appName = 'Nouvelle-Techno.fr';
- $secretKey : C'est une clé unique qui permet à Google Authenticator de générer des codes associés à ce compte utilisateur. Chaque utilisateur a sa propre clé.
- $_SESSION['user'] : Nous stockons la clé secrète et l'email de l'utilisateur dans la session. Cela servira lors de la vérification.
Générer un QR code pour l'application d'authentification
Une fois que la clé secrète est générée, nous devons générer un QR code contenant l'URL que Google Authenticator utilisera pour configurer l'authentification. Cette URL suit un format spécifique (otpauth://totp/...
).
Voici le code pour générer le QR code :
use BaconQrCode\Renderer\GDLibRenderer;
use BaconQrCode\Writer;
$qrCodeUrl = $google2FA->getQRCodeUrl($appName, $user['email'], $secretKey);
// On prépare le QRCode
$imageSize = 250;
$writer = new Writer(
new GDLibRenderer($imageSize)
);
// On encode l'url
$encodedQrCodeData = base64_encode($writer->writeString($qrCodeUrl));
Ensuite on affiche une image contenant le QR code à scanner avec l’application Google Authenticator.
<img src="data:image/png;base64,<?= $encodedQrCodeData ?>" alt="QR code">
- getQRCodeUrl() : Crée une URL dans le format
otpauth://totp/AppName:Email?secret=SecretKey
. Cette URL est ce que Google Authenticator scanne pour configurer le compte. - BaconQrCode : Cette bibliothèque génère l'image du QR code à partir de l'URL.
- base64_encode : Le QR code est encodé en base64 pour être directement affiché dans une balise
<img>
.
Vérifier le code généré
Une fois que l'utilisateur a configuré Google Authenticator en scannant le QR code, il pourra entrer le code affiché dans l'application. Nous allons créer un formulaire pour saisir ce code et le vérifier côté serveur.
Le formulaire dans index.php
:
<form id="verify" method="POST" action="verify.php">
<input type="text" name="code" placeholder="Entrez le code" required>
<button type="submit">Vérifier</button>
</form>
Le fichier verify.php
:
use PragmaRX\Google2FA\Google2FA;
require 'vendor/autoload.php';
session_start();
// On vérifie si on a un POST et si la session existe
if(empty($_POST['code']) || empty($_SESSION['user']['google2FA_secret'])){
die(json_encode(['result' => false]));
}
// On initialise Google2FA
$google2FA = new Google2FA();
// On récupère le code
$code = $_POST['code'];
$isValid = $google2FA->verifyKey($_SESSION['user']['google2FA_secret'], $code);
echo json_encode([
'code' => $code,
'result' => $isValid
]);
- verifyKey() : Cette fonction compare le code OTP saisi par l'utilisateur avec le code attendu pour la clé secrète. Si c'est correct,
$isValid
seratrue
.
Vérification et réponse via JavaScript
Enfin, nous utilisons du JavaScript pour gérer la soumission du formulaire et afficher les résultats sans recharger la page.
// On récupère le submit du formulaire
document.querySelector("#verify").addEventListener("submit", function(event){
// On empêche le submit
event.preventDefault();
// On récupère le code
let code = document.querySelector("#code").value;
if(!code){
alert("Merci d'entrer un code");
return false;
}
// On génère les données de formulaire
let formData = new FormData();
formData.append("code", code);
fetch("verify.php", {
method: "post",
body: formData
})
.then(response => response.json())
.then(data => {
if(!data.result){
alert("Code incorrect : " + data.code );
return false;
}
alert("Code correct : " + data.code);
});
});
- Nous utilisons fetch() pour envoyer le formulaire en AJAX, sans recharger la page.
- response.json() : Transforme la réponse de
verify.php
en objet JSON pour manipuler les données facilement.
Conclusion
Avec ce tutoriel, vous avez appris à implémenter une authentification à deux facteurs avec Google Authenticator en PHP. Vous avez généré une clé secrète unique pour chaque utilisateur, créé un QR code pour lier le compte avec Google Authenticator, et mis en place un système pour vérifier les codes OTP générés. Cela renforce la sécurité de votre application en ajoutant une couche supplémentaire d'authentification.
N'hésitez pas à adapter ce code à vos besoins, par exemple en stockant la clé secrète dans une base de données et en améliorant les validations et les erreurs pour une sécurité accrue.
Obtenir de l'aide
Pour obtenir de l'aide, vous pouvez accéder au serveur Discord pour une entraide par chat.