Les API (interfaces de programmation d'applications) constituent le tissu connectif du logiciel actuel : chaque paiement par carte, chaque connexion via un compte externe et chaque intégration entre systèmes passe par l'une d'elles. Cette centralité en fait également le principal vecteur d'attaque. Selon l'OWASP API Security Top 10, les vulnérabilités les plus exploitées ne sont pas des failles exotiques, mais des erreurs de conception dans l'autorisation et la validation. Développer une API sécurisée ne consiste pas à ajouter une couche à la fin, mais à prendre dès le premier endpoint les bonnes décisions d'architecture, d'authentification et de contrôle d'accès.
REST et GraphQL : quand choisir l'un ou l'autre
Le choix du style architectural conditionne le modèle de sécurité. REST organise l'API en ressources identifiées par URL et méthodes HTTP (GET, POST, PUT, DELETE), avec une surface d'attaque prévisible : chaque endpoint protège une ressource. GraphQL expose un unique endpoint sur lequel le client compose des requêtes flexibles, ce qui réduit la sur-collecte de données mais introduit des risques propres, comme des requêtes imbriquées susceptibles de provoquer un déni de service si leur profondeur et leur complexité ne sont pas limitées.
| Aspect | REST | GraphQL |
|---|---|---|
| Endpoints | Multiples, un par ressource | Un seul |
| Récupération des données | Risque de sur/sous-collecte | Le client demande exactement ce dont il a besoin |
| Cache HTTP | Natif et simple | Complexe (tout est POST) |
| Risque caractéristique | Endpoints exposés sans autorisation | Requêtes profondes et coûteuses |
Authentification versus autorisation : ce n'est pas la même chose
Confondre ces deux concepts est à l'origine de nombreuses brèches. L'authentification répond à « qui êtes-vous ? » et l'autorisation à « que pouvez-vous faire ? ». Le standard de référence pour déléguer l'accès est OAuth 2.0 (RFC 6749), qui permet à une application d'accéder à des ressources au nom de l'utilisateur sans manipuler son mot de passe, via des jetons d'accès. Sur OAuth 2.0 s'appuie OpenID Connect, qui ajoute la couche d'identité (savoir qui est l'utilisateur, pas seulement ce qu'il peut faire).
Pour le flux des applications serveur, on utilise l'Authorization Code Flow, et pour les applications publiques (SPA et mobile) on lui ajoute PKCE (Proof Key for Code Exchange, RFC 7636), qui empêche l'interception du code d'autorisation. Les jetons se matérialisent souvent sous forme de JWT (JSON Web Tokens) : des jetons signés que le serveur peut valider sans interroger une base de données. Il convient de conserver des access tokens à courte durée de vie et de déléguer le renouvellement à des refresh tokens à vie plus longue et révocables.
BOLA : la vulnérabilité numéro un
La première place de l'OWASP API Security Top 10 revient à BOLA (Broken Object Level Authorization). Elle survient lorsqu'un endpoint vérifie que l'utilisateur est authentifié, mais pas que l'objet demandé lui appartient. L'exemple classique : GET /api/factures/1043 retourne la facture correctement au propriétaire, mais si un autre utilisateur authentifié modifie l'identifiant en 1044 et reçoit la facture d'un tiers, l'API présente une vulnérabilité BOLA grave. La défense consiste à vérifier systématiquement, pour chaque opération, que le sujet authentifié a bien la permission d'agir sur l'objet précis, sans jamais faire confiance au fait qu'un identifiant difficile à deviner suffise comme protection.
Rate limiting et protection contre les abus
Sans limites de taux, une API reste exposée aux attaques par force brute sur les identifiants, au scraping massif et au déni de service. Le rate limiting restreint le nombre de requêtes par client dans une fenêtre temporelle. Les algorithmes les plus utilisés sont le token bucket (permet des rafales contrôlées), le leaky bucket (lisse le débit) et la fenêtre glissante (sliding window). Il est recommandé de communiquer les limites via des en-têtes standards tels que RateLimit-Limit et RateLimit-Remaining, et de répondre avec le code 429 Too Many Requests accompagné de l'en-tête Retry-After lorsque le seuil est dépassé.
Validation des entrées et prévention des injections
Toute entrée du client est hostile jusqu'à preuve du contraire. La validation doit appliquer le principe de liste blanche : définir explicitement ce qui est accepté (type, longueur, format, plage) et rejeter le reste, plutôt que d'essayer de filtrer ce qui est mauvais. Les requêtes vers la base de données doivent toujours utiliser des instructions paramétrées pour neutraliser l'injection SQL, et la sortie doit être encodée selon le contexte pour prévenir le XSS. Valider le schéma d'une requête avec des outils tels que JSON Schema ou la spécification OpenAPI permet de rejeter les requêtes malformées avant qu'elles n'atteignent la logique métier.
La passerelle API : un point de contrôle unique
À mesure que le nombre de services augmente, gérer la sécurité endpoint par endpoint devient ingérable. La passerelle API (API gateway) résout ce problème en se plaçant devant les services comme point d'entrée unique. Elle centralise les tâches transversales qui devraient sinon être réimplémentées dans chaque service : terminaison TLS, validation des jetons, application du rate limiting et des quotas, routage, transformation des requêtes et enregistrement du trafic. Concentrer ces fonctions dans la passerelle évite la duplication de la logique de sécurité et, surtout, les incohérences : un seul endroit où l'on décide qui peut appeler et à quelle fréquence.
La passerelle est également l'endroit naturel pour déployer le modèle de confiance zéro dans les communications internes. Dans les architectures de microservices modernes, les services s'authentifient mutuellement via mTLS (TLS mutuel), de sorte que chaque appel interne vérifie à la fois l'identité du client et celle du serveur. Ainsi, compromettre un seul service ne confère pas un accès libre au reste du système, car chaque saut exige toujours des identifiants valides.
Sécurité des webhooks
Les webhooks inversent le flux habituel : au lieu que le client interroge l'API, c'est le serveur qui notifie le client lorsqu'un événement se produit. Cela pose un risque différent, car le récepteur expose un endpoint public que n'importe qui pourrait invoquer. La défense standard est la vérification de signature : l'émetteur calcule un HMAC du corps du message avec un secret partagé et l'envoie dans un en-tête ; le récepteur recalcule la signature et la compare avant de traiter quoi que ce soit. Il convient également d'inclure un horodatage dans la signature pour prévenir les attaques par rejeu (replay) et de rejeter les messages anciens.
Étapes pour concevoir une API sécurisée
- Imposer HTTPS sur tous les endpoints ; ne jamais accepter de trafic en clair.
- Authentifier avec OAuth 2.0 / OpenID Connect et des jetons à courte durée de vie, en évitant les clés API statiques intégrées dans les clients.
- Autoriser au niveau de l'objet et de la fonction pour chaque requête, en appliquant le modèle du moindre privilège.
- Valider toutes les entrées selon un schéma et paramétrer les requêtes.
- Appliquer le rate limiting et des quotas par client, utilisateur et IP.
- Versionner l'API (
/v1/,/v2/) pour évoluer sans rompre les intégrations existantes. - Journaliser et surveiller les accès et les anomalies, sans vider des données sensibles dans les logs.
- Documenter avec OpenAPI et maintenir la documentation synchronisée avec le code.
Erreurs courantes
La première est l'autorisation brisée au niveau de l'objet (BOLA) décrite précédemment. La deuxième est l'exposition excessive de données : retourner l'objet complet depuis la base de données en faisant confiance au client pour n'afficher que les champs pertinents, alors que l'attaquant inspecte la réponse brute. La troisième est de ne pas limiter les ressources, laissant l'API ouverte à des paginations massives ou des requêtes GraphQL illimitées. La quatrième est la mauvaise gestion des secrets : clés et jetons dans le code source ou dans des dépôts. La cinquième, très fréquente, est l'API fantôme ou zombie : des endpoints d'anciennes versions toujours actifs sans maintenance ni protection.
Questions fréquentes
Qu'est-ce qui est préférable, une clé API ou OAuth 2.0 ? Les clés API identifient une application mais pas un utilisateur, et sont difficiles à faire pivoter et à révoquer. OAuth 2.0 offre des jetons à courte durée de vie, des périmètres de permission (scopes) et la révocation. Pour l'accès utilisateur, OAuth 2.0 avec OpenID Connect est le standard recommandé ; les clés API conviennent aux intégrations serveur à serveur à faible risque.
GraphQL est-il moins sécurisé que REST ? Non, pas intrinsèquement, mais il déplace le risque : avec REST on surveille chaque endpoint ; avec GraphQL il faut limiter la profondeur et la complexité des requêtes, appliquer des listes blanches d'opérations et désactiver l'introspection en production.
Où stocker les jetons dans une application web ? Pour les SPA, éviter localStorage à cause de son exposition aux XSS ; privilégier les cookies HttpOnly, Secure et SameSite, complétés par une protection CSRF. Pour les mobiles, utiliser le stockage sécurisé du système d'exploitation.
À quelle fréquence dois-je renouveler les identifiants ? Les access tokens doivent expirer en quelques minutes ou heures ; les secrets clients et les clés API doivent être renouvelés périodiquement et, obligatoirement, dès le moindre soupçon de fuite, via un processus de rotation automatisé et sans interruption de service.
Conclusion
La sécurité d'une API se gagne ou se perd dans la conception de l'autorisation, non dans la puissance du chiffrement. Le constat le plus révélateur de l'OWASP API Security Top 10 est que les failles dominantes (BOLA, autorisation brisée au niveau de la fonction, exposition excessive de données) sont des erreurs de logique métier qu'aucun outil automatique ne détecte entièrement : elles dépendent de la vérification, pour chaque opération, que cet utilisateur peut effectuer cette action sur cet objet. Une API moderne combine OAuth 2.0 avec PKCE, des jetons à courte durée de vie, une validation stricte par schéma, le rate limiting et l'observabilité, le tout versionné et documenté avec OpenAPI. Chez Summum, nous concevons et intégrons des API en appliquant ce modèle dès le premier endpoint, de sorte qu'ouvrir une intégration à un tiers ne signifie pas ouvrir une porte sur le reste du système.