Authentifier par jeton, et stocker son empreinte
Chaque client reçoit un jeton aléatoire long (au moins 32 octets issus de random_bytes()). En base, on ne stocke pas le jeton mais son empreinte : si la base fuit, les jetons ne sont pas réutilisables.
$jeton = bin2hex(random_bytes(32)); // remis une fois au client
$empreinte = hash('sha256', $jeton); // seule valeur stockée
// À chaque appel :
$recu = substr($_SERVER['HTTP_AUTHORIZATION'] ?? '', 7); // « Bearer … »
$ok = $ligne && hash_equals($ligne['empreinte'], hash('sha256', $recu));hash_equals() compare en temps constant : la durée de la comparaison ne renseigne pas un attaquant sur le nombre de caractères justes.
Jamais de jeton dans l'URL
Une URL finit dans les journaux du serveur web, dans ceux des proxys, dans l'historique. Sur beaucoup de serveurs, ces journaux sont lisibles bien au-delà de l'application. Le jeton voyage dans un en-tête (Authorization: Bearer …), et l'API refuse explicitement un jeton passé en paramètre plutôt que de l'accepter « pour dépanner ».
Requêtes préparées, toujours
Toute valeur venue du client passe par une requête préparée — y compris celles qui « ne peuvent être que des nombres ». Côté PDO, désactiver l'émulation des requêtes préparées (PDO::ATTR_EMULATE_PREPARES => false) fait préparer la requête par le serveur lui-même.
Attention au type des valeurs renvoyées : selon la version de PHP et ce réglage, une colonne entière peut revenir en int ou en chaîne. Pour une API dont les clients comparent "1" à 1, ce détail suffit à casser une application installée : figez les types dans la réponse JSON.
Versionner sans casser les applications installées
On ne modifie pas le comportement d'une API dont dépendent des applications déjà publiées. On publie une nouvelle version à côté (/v2/), on fait migrer les applications, et on ne retire l'ancienne qu'une fois qu'elle ne reçoit plus d'appels.
Pour le savoir, il faut des chiffres : un journal des appels par version permet de constater que plus personne n'utilise la v1 avant de l'arrêter. Et un interrupteur par version, dans le back-office, permet de couper une version en urgence sans toucher au code.
Journaliser, limiter, alerter
- Un journal des appels : date, version, point d'entrée, client, code de réponse, durée. Sans valeurs sensibles (ni jeton, ni mot de passe, ni contenu personnel inutile).
- Une limitation de débit par client et par adresse IP, pour qu'une application boguée en boucle ou un robot ne fassent pas tomber le service.
- Des secrets hors de la racine web : identifiants de base et clés dans un fichier de configuration que le serveur web ne peut pas servir, avec des droits restreints.
- Des erreurs muettes côté client : un message générique et un code HTTP cohérent ; le détail (requête, trace) va dans le journal du serveur, jamais dans la réponse.
Publié le 12/02/2026.