Clés API et services externes — ce que protège une clé, et les webhooks

Cet article fait partie du cours Les bases de l'informatique, qui construit depuis zéro les connaissances informatiques pratiques indispensables pour programmer et faire du vibe coding.
Une clé API est une chaîne de caractères qui indique à qui appartient l'appel. Des schémas montrent où tu peux la placer et dans quel sens va un webhook, la requête envoyée par le service externe vers ton serveur.

Cet article traite de deux sujets : la clé API utilisée pour appeler un service externe, et le webhook, appelé depuis le service externe.

Tu verras où la clé est émise, ce que cette chaîne indique, et où la placer pour que personne d'autre ne puisse la lire.

  • Où tu émets une clé API, et à quel endroit de l'appel tu la joins
  • Le fait qu'une clé soit une chaîne indiquant à qui appartient l'appel, et son lien avec la facturation à l'usage
  • Où une clé peut être placée, et ce qui arrive si tu l'écris à un endroit qui atteint le navigateur
  • Le webhook appelé depuis le service externe, et la vérification de la signature

La clé API s'émet dans le tableau de bord du service externe que tu utilises

Pour appeler un service externe, tu reçois d'abord du fournisseur une clé API (API key : une chaîne qui indique au fournisseur à quel utilisateur appartient un appel).

Ce n'est pas une valeur que tu choisis : c'est le service que tu utilises qui l'émet et te la remet.

Qu'il s'agisse de paiement, de cartographie ou de génération de texte, la séquence — s'inscrire, émettre une clé, la placer sur ton propre serveur — reste la même.

De l'émission de la clé API jusqu'à sa mise en place dans my-app
Site du serviceutiliséCréer un compteEnregistré commeutilisateurTableau de bordÉmettre unenouvelle cléTu reçois unelongue chaîneTon serveurÉcrire dans .envPeut accompagnerles appels
De haut en bas. À gauche l'endroit où tu travailles, au milieu ce que tu fais, à droite ce que tu obtiens là. La clé se crée dans le tableau de bord du fournisseur, et elle se place à l'intérieur de ton propre serveur.

Copie la chaîne émise sur-le-champ et place-la dans le fichier .env de ton propre serveur.

La plupart des services externes fonctionnent en facturation à l'usage (tu paies ce que tu consommes) : la facture dépend du nombre d'appels et du volume envoyé et reçu.

Si une clé fuite, les appels faits par d'autres entrent aussi dans la facture du titulaire.

La clé API est une chaîne qui indique à quel utilisateur appartient l'appel

L'API d'un service de paiement est une URL publique : il lui faut donc un moyen de savoir à qui appartient l'appel reçu.

Tu ne la joins pas à l'URL mais à l'en-tête de requête (request header : la partie, distincte du corps, qui aligne des couples nom-valeur comme l'expéditeur ou le format).

Une requête envoyée par my-app au service de paiement
Une requête envoyée par my-app
Ligne 1 — méthode et URL
  • POST https://api.pay.example.com/v1/charges
  • Uniquement où elle va et ce qu'elle y fait
À partir de la ligne 2 — en-têtes de requête
  • C'est ici que s'écrit la clé API
  • Authorization: Bearer sk_live_a1b2
  • Un couple nom-valeur par ligne
Après une ligne vide — le corps
  • Les données envoyées, en JSON
  • Souvent vide pour les appels qui ne font que lire
Le cadre extérieur représente une requête. Mettre la clé dans l'URL la laisse consignée aussi bien chez le fournisseur que sur ton propre serveur : elle se place donc dans l'en-tête, au milieu.

La deuxième ligne du cadre du milieu est celle où s'écrit la clé.

Authorization est le nom de l'en-tête, Bearer le mot qui indique la façon de transmettre la valeur, et ce qui suit est la valeur de la clé.

Ce nom comme cette écriture sont fixés par le fournisseur.

À partir de la clé reçue, le service de paiement détermine trois choses : le titulaire, les opérations autorisées et le nombre d'appels.

Ce que my-app a faitEn-tête AuthorizationCe que fait le service de paiementCe qui est renvoyé
Récupérer la liste des paiementsBearer sk_live_a1b2Détermine le titulaire et vérifie les droits200 et JSON
Récupérer la liste des paiementsOublié de la joindreNe peut pas déterminer le titulaire401
Créer un paiementBearer sk_read_9f3cSeule la lecture est autorisée403
Appeler de nombreuses fois en peu de tempsBearer sk_live_a1b2Compte les appels par titulaire429

Sur un 401, vérifie la valeur de la clé et le nom de l'en-tête ; sur un 403, les opérations autorisées.

La limite de la quatrième ligne est la limite de débit (rate limit : le nombre maximal d'appels acceptés sur une période donnée), et la dépasser renvoie 429.

La clé indique à qui appartient l'appel

Une clé API est une chaîne dont le seul rôle est de dire à qui appartient cet appel.

Le service de paiement lit la clé pour vérifier le titulaire et les opérations autorisées, et il compte les appels de cette personne : sans clé il renvoie 401, pour une opération non autorisée 403, et pour trop d'appels 429.

Garde la clé hors du code qui atteint le navigateur, uniquement à l'intérieur de ton serveur

Quiconque détient la clé peut appeler en tant que son titulaire.

Aucun mécanisme à l'écran ne vérifie qu'il s'agit bien de la bonne personne.

Où arrivent les fichiers de my-app
Tout my-app
À l'intérieur de ton serveur (n'atteint pas l'appareil)
.env
  • PAY_API_KEY=sk_live_a1b2
  • Rangée dans un fichier distinct du code
server.js
  • Joint à l'appel la clé lue dans .env
  • Le fichier lui-même n'est jamais envoyé à l'appareil
Ce qui atteint le navigateur (lisible par tous)
  • index.html et script.js
  • Demande à ton propre serveur au lieu d'appeler directement le service de paiement
  • Ne contient que les clés émises pour un usage depuis le navigateur
Les fichiers du cadre du haut ne quittent jamais ton propre serveur. Ceux du cadre du bas sont envoyés tels quels sur l'appareil de l'utilisateur.

Pour une même clé, l'endroit où tu l'écris change qui peut la lire.

Où la clé est écriteAtteint l'appareil ?Qui peut la lireCe qui arrive
.env (dans le serveur)Ne l'atteint pasSeulement ceux qui ont accès au serveurUtilisable comme prévu
script.jsL'atteintTous ceux qui ouvrent la pageD'autres peuvent appeler en ton nom
Un server.js publiéNe l'atteint pas, mais devient publicTous ceux qui voient le codeImpossible à effacer de l'historique Git

Plus une ligne élargit le cercle de ceux qui peuvent lire la clé, plus on approche de la situation où d'autres appellent en ton nom.

La troisième ligne n'atteint pas le navigateur, mais une fois enregistrée dans Git, elle reste lisible dans l'historique des modifications même si tu la supprimes ensuite.

Quand une consigne dit « mets-la dans .env », elle te demande le placement de la première ligne.

Face à une clé qui a fuité, deux actions sont possibles, et elles n'ont pas le même effet.

Ce que tu peux faire pour une clé qui a fuité
sk_live_a1b2a fuitéSupprimer la lignedu codeRévoquer dans letableau de bordLa valeur luereste utilisableAppels refusésavec cette clé
À gauche, tu ne fais qu'effacer les caractères écrits. À droite, la clé elle-même devient inutilisable du côté du service de paiement. Seule celle de droite entraîne le refus des appels.

La valeur lue par quelqu'un reste valide, et elle demeure aussi dans l'historique des modifications de Git.

Celle de droite, c'est la révocation (revoke : le fournisseur rend inutilisable une clé déjà émise).

Ne place la clé que là où elle n'atteint aucun appareil

Quiconque détient la clé peut l'utiliser en tant que son titulaire.

Ne l'écris donc ni dans les fichiers qui atteignent l'appareil de l'utilisateur ni dans le code que tu publies, et si elle fuite par inadvertance, révoque-la et émets-en une nouvelle au lieu d'effacer les caractères écrits.

Le webhook est le mécanisme par lequel le service externe appelle ton propre serveur

La fin d'un paiement ou un remboursement sont des événements dont l'appelant ne peut pas connaître le moment.

Demander sans arrêt multiplie les appels inutiles et retarde le moment où tu t'en aperçois.

Le webhook — le mécanisme par lequel, quand un événement déterminé se produit, le service externe envoie une requête vers une URL enregistrée d'avance — inverse ce sens.

Trois approches : laquelle des deux parties envoie la requête
=MéthodeQui envoieCe qu'il fautprévoirAppeler l'APImy-app →service paiementEndpoint etclé APIDemander en bouclesi c'est finimy-app →service paiementIntervalleWebhookService paiement →my-appURL my-app pourles notifications
Les deux premières lignes vont dans le même sens : elles sont donc reliées par un double trait. Seul le webhook va du service de paiement vers my-app.

Seul le webhook, en troisième ligne, va du service de paiement vers my-app.

Tout ce que tu prépares, c'est l'enregistrement d'une URL qui reçoit les notifications.

Les notifications issues d'un seul paiement
Un utilisateurpaie une foisPaiement terminéReçu crééRemboursé ensuitemy-app/webhooks/payment
Même pour un seul paiement, une notification distincte arrive pour chaque événement. Elles arrivent toutes à l'unique URL que tu as enregistrée.

Une notification distincte arrive quand le paiement se termine, quand le reçu est créé et quand un remboursement a lieu.

Le corps de la requête indique de quel événement il s'agit.

La flèche 1 va dans le sens où c'est toi qui appelles, la flèche 2 dans le sens où le service externe t'appelle.

La clé ne va qu'au service de paiement et n'atteint jamais l'appareil de l'utilisateur.

Le webhook est un appel en sens inverse

Le webhook est l'appel par lequel le service de paiement appelle my-app.

Il sert à te signaler, au moment où ils surviennent, des événements dont tu ne peux pas prévoir la date, et tout ce que tu prépares, c'est une URL de réception des notifications, créée et enregistrée à l'avance.

N'importe qui peut appeler l'URL qui reçoit les notifications : vérifie donc la signature avant de traiter

L'URL qui reçoit les notifications est publique, donc quelqu'un d'autre que le service de paiement peut envoyer vers cette même URL.

Ce qui l'empêche, c'est la signature — une valeur calculée à partir d'une chaîne connue du seul expéditeur et du seul destinataire, jointe à la requête, que le destinataire vérifie en refaisant le même calcul.

Une notification arrivée du service de paiement
Une requête reçue par my-app
Ligne 1 — méthode et URL
  • POST https://my-app.example.com/webhooks/payment
  • L'URL que tu as créée et enregistrée
À partir de la ligne 2 — en-têtes de requête
  • C'est ici qu'entre la signature
  • L'identifiant qui permet de reconnaître une notification répétée s'y trouve souvent aussi
Après une ligne vide — le corps
  • De quel événement il s'agit, écrit en JSON
  • L'identifiant du paiement et son état s'y trouvent aussi
Le cadre extérieur est une requête reçue. La signature entre dans l'en-tête, et le corps dit de quel événement il s'agit.

Vérifie la signature de l'en-tête avant de lire le contenu.

Quand tu ne renvoies pas de succès, l'expéditeur envoie une seconde fois la même notification : c'est le renvoi (retry).

Enregistre l'identifiant de chaque notification et ignore celles que tu as déjà traitées.

Comme la clé API, la chaîne utilisée pour la vérification reste hors du code, et la façon de la joindre se vérifie dans la documentation de l'API.

Quand un guide dit « vérifie la signature », c'est de cette vérification qu'il parle.

Vérifier avant de lire, et prévoir un second envoi

L'URL qui reçoit les notifications est publique, donc l'arrivée d'une requête ne dit rien sur son expéditeur.

Vérifie la signature avant de lire le corps, et si elle correspond, mets à jour l'enregistrement et renvoie un code de statut de succès, puis retiens les identifiants des notifications déjà traitées pour ignorer un second envoi.

QUIZ

Vérification des connaissances

Répondez à chaque question une par une.

Question 1Quand tu envoies une requête avec une clé API jointe, que peut déterminer le service externe ?

Question 2Quel est le problème si tu écris une clé API dans du code qui atteint le navigateur ?

Question 3Quand une notification de webhook arrive, que fais-tu avant d'en lire le contenu ?