Vous avez écrit une API, tout fonctionne, les tests sont réussis, le front-end tire les points de terminaison, tout est parfait. Et puis quelqu'un verse le jeton dans un dépôt public, le bot commence à marteler votre serveur avec 10 000 requêtes par seconde, et le stagiaire supprime accidentellement la base de production via l'API.
Bienvenue dans le monde de la sécurité des API. Examinons les trois principaux piliers sur lesquels tout repose, et où les développeurs trébuchent le plus souvent.

🎫 1. Jetons : votre laissez-passer numérique
Qu'est-ce que c'est et pourquoi ?
Un jeton est une chaîne qui dit au serveur : « Je suis celui que je prétends être. » Sans jeton, toute requête à l'API sécurisée recevra un 401 Unauthorized froid en réponse.
Les schémas les plus populaires :
API Key — une clé simple dans l'en-tête ou le paramètre de requête. Pratique, mais grossier.
JWT (JSON Web Token) — jeton autonome avec payload, signature et durée de vie.
OAuth 2.0 Access Token — délivré via le serveur d'autorisation, idéal pour les applications tierces.
Où sont les jambages ?
❌ Stockage de jetons dans le code
Classique du genre. Le développeur écrit const API_KEY = "sk-live-abc123..." directement dans les sources. Il pousse dans GitHub. Le bot trouve la clé en 30 secondes. Bonjour, fuite.
// ❌ Seuls les ennemis font cela à eux-mêmesconst API_KEY = "sk-live-abc123def456";
// ✅ Les variables d'environnement sont notre toutconst API_KEY = process.env.API_KEY ;❌ Jetons sans durée de vie
Un jeton a été émis, et il vit éternellement. S'il est volé, l'attaquant obtient un accès illimité. JWT sans exp est comme une clé d'appartement qui ne peut pas être réémise.
❌ Transfert de jetons via URL
Lorsque le jeton vole dans le paramètre de requête (?token=abc123), il se dépose dans les journaux du serveur, dans l'historique du navigateur, dans les analyses. Toujours utiliser l'en-tête Authorization :
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
❌ Absence de rotation
La même clé est utilisée depuis des années. La règle est simple : changez régulièrement de clés et utilisez une paire de jetons d'accès/de rafraîchissement.
🚦 2. Limitation de débit : freins pour l'API
Qu'est-ce que c'est et pourquoi ?
La limite de débit est une limite sur le nombre de demandes par unité de temps. Sans cela, un client agressif (ou un bot) peut mettre fin à l'ensemble du service.
Où sont les jambages ?
❌ La limite de débit n'est pas configurée du tout
Étonnamment, de nombreuses API sont mises en production sans aucune restriction. Tant que le trafic est faible, il n'y a pas de problème. Mais la première attaque DDoS ou un script imprudent avec une boucle infinie - et le serveur tombe en panne.
❌ Limite par IP uniquement
Cela semble logique, mais un bureau entier ou un VPN peut se cacher derrière une seule adresse IP. Et un attaquant peut distribuer des requêtes à des milliers d'adresses. Il est préférable de limiter par jeton/utilisateur :
# Exemple avec Redis sur Pythondef check_rate_limit(user_id) :
key = f"rate:{user_id}"
current = redis.incr(key)
if current == 1:
redis.expire(key, 60) # fenêtre - 60 secondes
if current > 100:
raise RateLimitExceeded()❌ Aucune réponse informative
Lorsque le client atteint la limite, il doit comprendre ce qui s'est passé. Donnez 429 Too Many Requests et des titres utiles :
HTTP/1.1 429 Too Many Requests
Retry-After: 30
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1700000000
❌ Limites identiques pour tous les points de terminaison
Les requêtes GET /users et POST /payments sont des opérations complètement différentes en termes de charge et de criticité. Les opérations lourdes et sensibles (paiement, envoi de lettres, génération de rapports) doivent avoir des limites plus strictes.

👑 3. Droits d'accès : tous ne sont pas égaux
Qu'est-ce que c'est et pourquoi ?
Même si l'utilisateur est authentifié (nous savons qui il est), cela ne signifie pas qu'il peut tout faire. L'autorisation répond à la question « qu'est-ce qui vous est exactement permis ? ».
Où sont les jambages ?
❌ Vérification des droits uniquement sur le frontend
Le bouton « Supprimer » est-il masqué dans l'interface utilisateur pour un utilisateur normal ? Super. Mais s'il envoie directement DELETE /api/users/42 via curl, le serveur exécutera la requête. La vérification des droits doit être sur le backend. Toujours.
// ❌ Front-end « protection »
{role === 'admin' && <button onClick={deleteUser}>Удалить</button>}
// ✅ Vérification du backend — obligatoire
app.delete('/api/users/:id', (req, res) => {
if (req.user.role !== 'admin') {
return res.status(403).json({ error: 'Forbidden' });
}
// ... suppression
});❌ IDOR — Insecure Direct Object Reference
L'une des vulnérabilités les plus courantes. L'utilisateur demande GET /api/orders/123 et voit sa commande. Il change 123 en 124 et voit la commande de quelqu'un d'autre. Le serveur ne vérifie pas si la ressource appartient à l'utilisateur actuel :
// ❌ Nous faisons confiance à l'ID de l'URL sans vérifier le propriétaire
app.get('/api/orders/:id', async (req, res) => {
const order = await Order.findById(req.params.id);
res.json(order); // n'importe quelle commande
});
// ✅ Filtrer par propriétaire
app.get('/api/orders/:id', async (req, res) => {
const order = await Order.findOne({
_id: req.params.id,
userId: req.user.id // seulement vos commandes
});
if (!order) return res.status(404).json({ error: 'Not found' });
res.json(order);
});❌ Portée trop large des jetons
OAuth vous permet d'émettre des jetons avec des droits limités (scopes). Mais les développeurs demandent souvent scope: * — un accès complet à tout. Si un tel jeton est divulgué, les conséquences seront maximales. Le principe des privilèges minimaux : donnez exactement autant de droits que nécessaire pour une tâche spécifique.
❌ Pas de séparation des rôles
Deux types d'utilisateurs : « autorisé » et « non autorisé ». Et il faut : admin, manager, user, readonly, service. Un modèle de rôle compétent n'est pas de la sur-ingénierie, mais une nécessité.
🚀 Voulez-vous aller plus loin ?
Si tu commences tout juste ton parcours en programmation ou si tu veux améliorer tes compétences pratiques, essaie Code. C'est une application dans laquelle tu apprends la programmation par la pratique : tu ne fais pas que lire la théorie, mais tu écris immédiatement du code et résous des problèmes.
Et aussi, visitez notre communauté Telegram — des articles utiles sur le développement, l'analyse des tâches et les nouveaux matériaux y sont régulièrement publiés. Nous sommes déjà plus de 2000 développeurs !
Ne soyez pas le développeur dont l'API fait l'actualité. Vérifiez votre liste de contrôle aujourd'hui. 🔒
