Introduction : pourquoi OAuth 2.0 et JWT sont nécessaires en PHP
Les applications web modernes fonctionnent rarement de manière isolée. Les utilisateurs s'attendent à une connexion unique via Google, Facebook ou GitHub, et les développeurs à un échange sécurisé de données entre microservices. Deux protocoles clés — OAuth 2.0 (délégation d'accès) et JWT (format de jeton compact) — sont devenus le standard de facto. Dans cet article, nous allons voir comment implémenter OAuth 2.0 et l'autorisation JWT en PHP à partir de zéro, en utilisant uniquement les fonctionnalités intégrées du langage et des bibliothèques populaires. Vous obtiendrez des exemples de code prêts à l'emploi pour l'intégration avec des fournisseurs externes et la création de votre propre système d'authentification.
1. Bases d'OAuth 2.0 : flux et rôles
OAuth 2.0 est un protocole d'autorisation qui permet aux applications tierces d'obtenir un accès limité aux ressources d'un utilisateur sans transmettre de mot de passe. Quatre rôles y participent :
- Resource Owner — l'utilisateur propriétaire des données.
- Client — votre application PHP demandant l'accès.
- Authorization Server — le serveur délivrant les jetons (par exemple, Google).
- Resource Server — l'API fournissant les données via le jeton.
Le flux le plus populaire pour les applications web est Authorization Code Grant. Il est sécurisé car le jeton est transmis via la partie serveur, et non via le navigateur. Examinons son implémentation en PHP.
1.1. Enregistrement de l'application et obtention du Client ID/Secret
Avant d'écrire le code, enregistrez votre application auprès du fournisseur (par exemple, dans Google Cloud Console). Vous obtiendrez client_id et client_secret, et configurerez l'URI de redirection (par exemple, https://votresite.fr/callback.php).
1.2. Implémentation du flux Authorization Code en PHP
Créons deux fichiers : login.php (redirection vers le serveur d'autorisation) et callback.php (traitement de la réponse).
Fichier login.php
<?phpsession_start();
$client_id = 'VOTRE_CLIENT_ID';$redirect_uri = 'https://votresite.fr/callback.php';$state = bin2hex(random_bytes(16)); // protection contre CSRF$_SESSION['oauth_state'] = $state;
$params = http_build_query([ 'client_id' => $client_id, 'redirect_uri' => $redirect_uri, 'response_type' => 'code', 'scope' => 'openid email profile', 'state' => $state,]);
header('Location: https://accounts.google.com/o/oauth2/v2/auth?' . $params);exit;?>Fichier callback.php
<?phpsession_start();
// Vérification du state (CSRF)if ($_GET['state'] !== $_SESSION['oauth_state']) { die('Erreur : state invalide');}
$client_id = 'VOTRE_CLIENT_ID';$client_secret = 'VOTRE_CLIENT_SECRET';$redirect_uri = 'https://votresite.fr/callback.php';
// Échange du code contre un jeton$ch = curl_init('https://oauth2.googleapis.com/token');curl_setopt($ch, CURLOPT_POST, true);curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ 'code' => $_GET['code'], 'client_id' => $client_id, 'client_secret' => $client_secret, 'redirect_uri' => $redirect_uri, 'grant_type' => 'authorization_code',]));curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);$response = curl_exec($ch);curl_close($ch);
$data = json_decode($response, true);$access_token = $data['access_token'] ?? null;
// Obtention du profil utilisateur$ch = curl_init('https://www.googleapis.com/oauth2/v2/userinfo');curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $access_token]);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);$userInfo = json_decode(curl_exec($ch), true);curl_close($ch);
echo 'Bonjour, ' . htmlspecialchars($userInfo['email']);?>Important : Vérifiez toujours le paramètre state. Il protège contre la falsification de requête (CSRF).