Gérer l'authentification dans les intégrations : OAuth, clés API et scopes
Quand utiliser des clés API plutôt qu'OAuth, comment fonctionnent les scopes et le rafraîchissement de jeton, et les pièges de sécurité à éviter.
L'authentification est le premier code qu'un ingénieur partenaire écrit contre votre API, et le premier endroit où il décide si construire sur votre plateforme sera agréable ou pénible. Tout ce qui précédait n'était qu'une conversation. Désormais, quelqu'un a un terminal ouvert, un jeu d'identifiants dont il ignore l'usage exact, et un manager qui attend une estimation. S'il parvient à un appel authentifié en quelques minutes, votre intégration avance. S'il passe un après-midi à deviner un flux de jetons que votre documentation ne décrit qu'en prose, votre intégration recule d'un cran dans sa feuille de route.
Les décisions d'authentification survivent aussi au lancement. Le choix entre clés API et OAuth, la façon dont vous délimitez les accès, la gestion du rafraîchissement des jetons et l'endroit où vous stockez les secrets façonnent tous ce qui se passera quand un problème surviendra deux ans plus tard. Un modèle d'authentification faible ne se signale pas de lui-même. Il reste silencieux jusqu'à ce qu'une clé fuitée, un jeton trop large ou un bug de rafraîchissement se transforme en fil de support, en revue de sécurité ou en e-mail de divulgation.
Ce guide porte sur la façon de prendre ces décisions correctement. Quand recourir aux clés API et quand OAuth justifie sa complexité, comment concevoir des scopes qui passent la propre revue de sécurité d'un partenaire, comment doivent réellement fonctionner les durées de vie et le rafraîchissement des jetons, et les pièges qui accumulent silencieusement du risque. Ce guide complète notre guide pour rendre votre API prête pour les partenaires, qui couvre la surface plus large de la documentation, du bac à sable et des webhooks, et approfondit la section sur laquelle les partenaires butent le plus.
L'essentiel en 60 secondes
- L'authentification est votre première impression en code. Un partenaire juge votre API à la vitesse à laquelle il atteint un appel authentifié, pas à votre liste de fonctionnalités.
- Les clés API sont pour le serveur à serveur, les données propres d'un seul client et le prototypage rapide. OAuth est pour les applications agissant au nom de nombreux utilisateurs, et la plupart des places de marché l'exigent.
- Si vous ne pouvez livrer qu'un seul mécanisme, livrez des clés API à scopes et mettez OAuth sur une feuille de route publique. Si vous servez des applications de place de marché, OAuth vous sera nécessaire.
- Les scopes doivent correspondre à des cas d'usage réels.
read:contactsetwrite:contactsvalent mieux qu'un unique scopeapi.access, car on demande aux partenaires de justifier chaque permission requise. - Documentez les durées de vie des jetons et le rafraîchissement avec des chiffres. Les partenaires devraient rafraîchir selon un calendrier, et non découvrir l'expiration via des
401en production. - La plupart des incidents d'authentification sont prévisibles : clés dans le contrôle de version, jetons sans expiration, secrets dans les URL, absence de révocation, et aucune vérification de scope côté serveur.
- Traitez l'authentification comme une surface produit, avec un exemple complet fonctionnel, des identifiants en libre-service et un catalogue d'erreurs qui explique chaque échec.
Clés API ou OAuth : la décision qui façonne tout
Presque chaque conversation sur l'authentification des intégrations commence ici, et les équipes la compliquent souvent à l'excès. Les deux modèles résolvent des problèmes différents, et la bonne réponse dépend de qui l'identifiant représente et de ce à quoi il a le droit de toucher.
Une clé API est un secret à longue durée de vie qui identifie un seul compte ou service. L'appelant l'envoie à chaque requête, généralement dans un en-tête Authorization, et le serveur la compare à une valeur stockée. Pas d'utilisateur dans la boucle, pas d'écran de consentement, pas de poignée de main. Cette simplicité est tout l'intérêt. Un partenaire peut coller une clé dans une variable d'environnement et effectuer un appel en deux minutes.
OAuth 2.0 est un cadre d'autorisation, et non un flux unique, défini dans le RFC 6749. Il existe pour résoudre un problème plus difficile : permettre à une application d'agir au nom d'un utilisateur sans que celui-ci ne livre son mot de passe. L'utilisateur approuve un ensemble précis de permissions, l'application reçoit un jeton délimité à ces permissions, et le jeton peut être révoqué ou expiré sans toucher à quoi que ce soit d'autre que l'utilisateur possède. Cette puissance coûte un effort d'implémentation des deux côtés.
Voici la décision présentée comme la plupart des équipes ont besoin de la voir :
| Clés API | OAuth 2.0 | |
|---|---|---|
| Représente | Un seul compte ou service | Un utilisateur qui a donné son consentement |
| Idéal pour | Serveur à serveur, données propres d'un client | Applications agissant au nom de nombreux utilisateurs |
| Effort d'intégration du partenaire | Quelques minutes | Plusieurs jours, même avec une bonne documentation |
| Granularité | Souvent tout ou rien | Scopes par permission |
| Consentement | Aucun, le titulaire du compte émet la clé | Écran d'approbation explicite de l'utilisateur |
| Révocation | Manuelle, par clé | Par utilisateur, flux standard |
| Durée de vie du jeton | Souvent indéfinie jusqu'à rotation | Accès à courte durée plus rafraîchissement |
| Référencement en place de marché | Souvent non accepté | Généralement requis |
La recommandation honnête pour la plupart des startups SaaS B2B est de prendre en charge les deux, dans cet ordre. Les clés API permettent à un partenaire de prototyper dès le premier jour et couvrent la large catégorie d'intégrations où un client connecte simplement son propre compte à ses propres systèmes. OAuth est ce qu'une application multi-locataires, et presque toute revue de place de marché, finira par exiger. Si vous ne pouvez en construire qu'un pour l'instant, construisez des clés API avec scopes et mettez OAuth sur une feuille de route publique, afin que les partenaires puissent l'anticiper. L'exception : si vos partenaires à court terme sont des applications de place de marché agissant au nom d'utilisateurs finaux, OAuth vous sera nécessaire plus tôt que prévu, et un lancement basé uniquement sur des clés bloquera leur revue. Nous expliquons comment cela influence les conversations avec les partenaires dans le guide de l'API prête pour les partenaires.
Une distinction à garder claire, car elle cause une réelle confusion : les clés API gèrent l'authentification (qui appelle) et, si vous les délimitez par scopes, une forme grossière d'autorisation (ce qu'elles peuvent faire). OAuth porte fondamentalement sur l'autorisation déléguée, un utilisateur accordant à une application la permission d'agir en son nom. Confondre les deux mène à des conceptions où les équipes recourent à OAuth alors qu'une clé API à scopes aurait été plus simple, ou livrent une clé API brute alors qu'elles avaient en réalité besoin du consentement de l'utilisateur.
Comment transmettre une clé sans la divulguer
Si vous prenez en charge les clés API, la façon dont le partenaire les envoie compte autant que la clé elle-même. La convention établie est l'en-tête Authorization, documentée dans la référence MDN de l'en-tête Authorization. Une requête typique consiste à envoyer Authorization: Bearer sk_live_... sur TLS. C'est tout le mécanisme, et la simplicité est une qualité.
Le piège que la plupart des équipes livrent au moins une fois est d'accepter la clé en paramètre de requête, par exemple un ?api_key=... dans l'URL. Cela semble pratique, et un exemple curl avec la clé dans l'URL est facile à copier. C'est aussi l'une des façons les plus courantes de divulguer des secrets. Les URL finissent dans les journaux d'accès des serveurs, les journaux de proxy, l'historique du navigateur, les pipelines d'analyse et l'en-tête Referer envoyé à des tiers. Un secret qui voyage dans une URL a de fait été écrit dans une douzaine d'endroits que vous ne contrôlez pas. Mettez la clé dans un en-tête, ne documentez que la forme par en-tête, et si vous devez accepter un paramètre de requête pour une raison héritée, traitez toute clé arrivant ainsi comme compromise et imposez une rotation.
Quelques pratiques supplémentaires rendent l'authentification par clé implémentable et sûre :
- Préfixez et étiquetez vos clés. Une clé qui commence par
sk_live_ousk_test_indique à son détenteur, et à tout outil d'analyse de secrets, ce qu'elle est et quel environnement elle touche. Cette seule convention intercepte une part notable des commits accidentels avant qu'ils ne deviennent des incidents. - Distinguez test et production. Un partenaire qui vous évalue à 21 h devrait pouvoir générer une clé de test contre un bac à sable sans toucher aux données de production. Mélanger les deux est la façon dont un prototype écrit dans le compte d'un vrai client.
- Stockez des empreintes, pas des clés. Conservez une empreinte (hash) de chaque clé dans votre base de données, et non la clé elle-même, comme vous le feriez pour des mots de passe. Si votre base de données est exposée, les clés ne sont pas exploitables. Montrez la clé complète à l'utilisateur exactement une fois, à la création.
- Faites de la rotation un bouton, pas un ticket. Les partenaires devront faire tourner leurs clés, après la perte d'un ordinateur portable ou le départ d'un employé. Si la rotation exige d'envoyer un e-mail à votre support, elle ne se fera pas au rythme qu'exige la sécurité.
Scopes : le moindre privilège qu'un partenaire peut réellement demander
Les scopes sont l'endroit où une authentification grossière devient une bonne authentification. Un scope est une permission nommée attachée à un identifiant, et une liste de scopes bien conçue permet à un partenaire de demander exactement l'accès dont son intégration a besoin, et rien de plus. Ce n'est pas de la bureaucratie. Quand la propre équipe de sécurité d'un partenaire examine l'intégration, la première question est « pourquoi cette application a-t-elle un accès en écriture à tout », et une liste de scopes restreinte est la réponse qui fait passer la revue.
Le schéma d'échec est un unique scope tout-puissant, du genre api.access ou full, qui accorde tout. Il est facile à construire et impossible à défendre. Un partenaire qui ne fait que lire des contacts est forcé de demander, et de détenir, la permission de supprimer des factures. Quand cet identifiant fuite, le rayon d'impact est toute la surface de votre API au lieu d'un seul point de terminaison en lecture.
Concevez les scopes autour de cas d'usage réels, généralement découpés par ressource et par action :
| Scope | Accorde | Usage typique |
|---|---|---|
read:contacts |
Lire les enregistrements de contacts | Une synchronisation CRM qui importe vos données |
write:contacts |
Créer et mettre à jour des contacts | Une synchronisation bidirectionnelle ou une intégration de formulaire |
read:events |
Lire les données d'événements ou d'activité | Une intégration d'analyse ou de reporting |
write:webhooks |
Enregistrer et gérer des webhooks | Toute intégration nécessitant des mises à jour poussées |
read:billing |
Lire les factures et abonnements | Un outil de finance ou de rapprochement |
Quelques principes maintiennent un système de scopes honnête. Nommez les scopes selon ce qu'un humain demanderait, et non selon des noms de tables internes, afin que l'écran de consentement vu par un utilisateur soit lisible. Séparez la lecture de l'écriture, pour que l'intégration courante en lecture seule n'ait jamais à demander l'écriture. Par défaut, choisissez le scope le plus étroit qui accomplit la tâche, et rendez évident dans votre documentation quels scopes chaque cas d'usage requiert, afin qu'un partenaire ne sur-demande pas par incertitude. Et surtout, appliquez les scopes côté serveur pour chaque requête, et pas seulement à l'écran de consentement. Un scope qui est affiché mais jamais vérifié est de la mise en scène. Le jeton peut indiquer read:contacts, mais si votre point de terminaison ne le vérifie pas avant de supprimer un contact, le scope n'a protégé personne.
Quand un appelant atteint un point de terminaison pour lequel il n'a pas le scope, renvoyez un 403 clair qui nomme le scope manquant, et non une erreur générique. La différence entre « 403 Forbidden » et « 403 : ce point de terminaison requiert le scope write:contacts » est la différence entre un après-midi de débogage et une correction de trente secondes. Nous traitons ce style d'erreur en libre-service en détail dans notre guide de conception des erreurs d'API.
Durées de vie des jetons et rafraîchissement, documentés avec des chiffres
Dès que vous prenez en charge OAuth, ou toute authentification basée sur des jetons, vous héritez d'un cycle de vie : les jetons sont émis, ils expirent, et ils sont rafraîchis. La façon dont vous concevez et documentez ce cycle de vie décide si les partenaires construisent quelque chose de stable ou quelque chose qui casse à 2 h du matin.
Le schéma OAuth standard utilise deux jetons. Un jeton d'accès à courte durée de vie est envoyé à chaque appel d'API, suivant l'usage du jeton porteur (bearer token) défini dans le RFC 6750. Un jeton de rafraîchissement à plus longue durée de vie sert uniquement à obtenir de nouveaux jetons d'accès quand l'ancien expire. Les séparer limite les dégâts : si un jeton d'accès fuite, il est inutilisable au bout d'une heure environ, et le jeton de rafraîchissement, plus sensible, voyage bien moins souvent et ne vit que côté serveur.
La règle qui prévient la plupart des bugs de jetons est simple : les partenaires devraient rafraîchir selon un calendrier, et non découvrir l'expiration via des 401 en production. Cela ne fonctionne que si vous leur fournissez les chiffres. Documentez, avec des valeurs concrètes, la durée de vie d'un jeton d'accès, celle d'un jeton de rafraîchissement, le fait que les jetons de rafraîchissement tournent ou non à l'usage, et exactement à quoi ressemble une réponse de jeton expiré afin qu'ils puissent la gérer dans le code.
| Question du partenaire | Ce que votre documentation doit indiquer |
|---|---|
| Combien de temps vit un jeton d'accès ? | Un chiffre concret, par exemple une heure |
| Combien de temps vit un jeton de rafraîchissement ? | Un chiffre concret, ou « jusqu'à révocation », clairement énoncé |
| Les jetons de rafraîchissement tournent-ils à l'usage ? | Oui ou non, et ce qui advient de l'ancien |
| Que renvoie un jeton d'accès expiré ? | Le statut exact et le corps d'erreur, par exemple 401 avec un code |
| Un partenaire peut-il rafraîchir de manière proactive ? | Si le rafraîchissement anticipé est autorisé et toute limite associée |
| Que se passe-t-il quand un utilisateur révoque l'accès ? | L'erreur que voit le partenaire et comment redonner le consentement |
Deux choix de conception méritent une décision délibérée plutôt qu'une valeur par défaut. Premièrement, la rotation des jetons de rafraîchissement : émettre un nouveau jeton de rafraîchissement à chaque utilisation, et invalider l'ancien, vous permet de détecter le vol de jeton, car un jeton de rafraîchissement volé puis rejoué apparaît comme la réutilisation d'un jeton déjà consommé. Cela ajoute de la complexité pour le partenaire, qui doit toujours conserver le jeton de rafraîchissement le plus récent, alors documentez-le clairement si vous le faites. Deuxièmement, ce qu'un partenaire fait sur un 401 : le comportement correct est de rafraîchir une fois et de réessayer, puis d'échouer bruyamment si le rafraîchissement échoue aussi. Les partenaires qui réessaient au contraire le même jeton expiré en boucle vont marteler votre point de terminaison d'authentification et appeler cela une panne. Détaillez le flux attendu pour qu'ils le construisent correctement dès la première fois.
Erreurs fréquentes, et comment les corriger
Clés validées dans le contrôle de version. La façon la plus courante de divulguer des secrets. La correction : préfixez les clés pour que les outils d'analyse les reconnaissent, ne stockez que des empreintes, prenez en charge la rotation en un clic, et indiquez aux partenaires dans votre documentation d'utiliser des variables d'environnement ou un gestionnaire de secrets, jamais un fichier de configuration versionné. Considérez comme grillée toute clé ayant transité par un dépôt.
Jetons qui n'expirent jamais. Un jeton d'accès sans expiration est une responsabilité permanente dès l'instant où il fuite, car rien ne réduit sa valeur avec le temps. La correction : des jetons d'accès à courte durée de vie avec rafraîchissement, dont les durées de vie sont documentées. Si vous devez émettre des clés API à longue durée de vie, rendez la révocation et la rotation sans effort pour compenser.
Secrets dans les URL. Les clés ou jetons dans les chaînes de requête finissent dans les journaux, l'historique et l'en-tête Referer. La correction : n'acceptez les identifiants que dans l'en-tête Authorization, ne documentez que cette forme, et traitez tout identifiant arrivant dans une URL comme compromis.
Scopes affichés mais jamais appliqués. Un écran de consentement qui liste read:contacts alors que le serveur laisse le jeton tout écrire est pire que pas de scopes du tout, car il sous-entend une protection qui n'existe pas. La correction : vérifiez le scope côté serveur pour chaque requête, et renvoyez un 403 qui nomme le scope manquant.
Ne documenter que le chemin idéal. Une documentation d'authentification qui montre un appel réussi et s'arrête force le partenaire à reconstituer l'expiration, le rafraîchissement, les erreurs de scope et la révocation. La correction : documentez tout le cycle de vie avec de vrais corps de réponse, y compris chaque échec. C'est la section sur laquelle les ingénieurs partenaires butent, alors elle mérite le plus de détails.
Aucun moyen de révoquer. Quand la clé d'un partenaire ou le jeton d'un utilisateur est compromis, il faut pouvoir le tuer immédiatement. La correction : une révocation par clé pour les clés API, des flux de révocation par utilisateur standard pour OAuth, et un guide documenté « que faire si un identifiant fuite ». Le projet OWASP API Security répertorie comment les défaillances d'authentification et d'autorisation apparaissent dans de vraies API, et il mérite d'être lu en regard de votre propre conception.
Comment les choix d'authentification changent la conversation d'intégration
L'authentification n'est pas qu'un détail d'ingénierie. Comme le reste de la préparation d'une API pour les partenaires, elle change ce qu'un partenaire peut vérifier par rapport à ce qu'il doit prendre sur parole. Chaque manque le force à vous faire confiance. Chaque élément documenté et fonctionnel lui permet de vérifier par lui-même, et les partenariats avancent au rythme de la vérification.
| Ce que demande le partenaire | Ce qui y répond |
|---|---|
| « Comment s'authentifie-t-on ? » | Un exemple complet, des identifiants jusqu'à un appel réussi |
| « Notre ingénieur peut-il essayer ce soir ? » | Des identifiants de test en libre-service, sans barrière commerciale |
| « Que peut réellement faire ce jeton ? » | Une liste de scopes mappée aux cas d'usage |
| « Comment gardons-nous les jetons à jour ? » | Des durées de vie documentées et un flux de rafraîchissement |
| « Que se passe-t-il en cas de fuite ? » | Une révocation par identifiant et un chemin de rotation |
| « Cela passera-t-il notre revue de sécurité ? » | Des scopes au moindre privilège, un stockage par empreinte, des secrets en en-tête uniquement |
Lisez ce tableau du point de vue du partenaire et le schéma correspond au reste de la préparation pour les partenaires : l'objectif est de permettre à un ingénieur de répondre à chaque question depuis votre documentation et un terminal, sans réserver d'appel. Quand l'authentification est solide, la conversation dépasse le « est-il sûr de construire là-dessus » et passe directement au cadrage de l'intégration, qui est la conversation que vous voulez avoir. Pour savoir comment le versionnage interagit avec tout cela sur la durée de vie d'une intégration, voyez notre guide du versionnage des intégrations.
FAQ
Devons-nous utiliser des clés API ou OAuth pour nos intégrations ? Les deux, si possible. Les clés API conviennent aux intégrations serveur à serveur et à un seul client connectant son propre compte, et elles permettent à un partenaire de prototyper en quelques minutes. OAuth convient aux applications agissant au nom de nombreux utilisateurs et est généralement requis pour les référencements en place de marché. Si vous en livrez un d'abord, livrez des clés API à scopes et mettez OAuth sur une feuille de route publique, sauf si vos partenaires à court terme sont des applications de place de marché, auquel cas priorisez OAuth.
Que sont les scopes et pourquoi importent-ils ?
Un scope est une permission nommée attachée à un identifiant, comme read:contacts ou write:webhooks. Ils importent parce qu'ils permettent à un partenaire de demander l'accès minimal dont son intégration a besoin, ce qui est exactement ce que sa propre revue de sécurité exigera. Un unique scope large signifie que tout identifiant fuité expose l'ensemble de votre API, tandis que des scopes restreints contiennent le rayon d'impact à une seule ressource et action.
Combien de temps les jetons d'accès devraient-ils vivre ?
Peu de temps, afin qu'un jeton fuité soit vite inutilisable, associé à un jeton de rafraîchissement pour le renouvellement. Le chiffre exact vous appartient, mais quel qu'il soit, documentez-le avec une valeur concrète et documentez le flux de rafraîchissement à côté. L'objectif est que les partenaires rafraîchissent selon un calendrier plutôt que de découvrir l'expiration via des erreurs 401 en production.
Où les partenaires devraient-ils envoyer les clés API ?
Dans l'en-tête Authorization sur TLS, et nulle part ailleurs. N'acceptez jamais les clés dans une chaîne de requête, car les URL fuitent dans les journaux, l'historique du navigateur et l'en-tête Referer envoyé à des tiers. Ne documentez que la forme par en-tête, et traitez toute clé arrivant dans une URL comme compromise.
Qu'est-ce que la rotation des jetons de rafraîchissement et en avons-nous besoin ? La rotation émet un nouveau jeton de rafraîchissement à chaque utilisation et invalide l'ancien, ce qui vous permet de détecter le vol quand un jeton volé est rejoué. C'est un contrôle solide mais qui ajoute de la complexité pour les partenaires, qui doivent toujours stocker le jeton de rafraîchissement le plus récent. Si vous l'adoptez, documentez-le bien en évidence pour que les partenaires le prennent en compte dès le départ.
Comment permettre aux partenaires de récupérer après la fuite d'un identifiant ? Rendez la révocation et la rotation en libre-service et rapides : une révocation par clé pour les clés API, une révocation par utilisateur standard pour OAuth, et un court guide dans votre documentation décrivant quoi faire en cas de fuite d'un identifiant. Si la récupération exige d'envoyer un e-mail à votre support, elle ne se fera pas au rythme qu'exigent les incidents de sécurité.
Les clés API ont-elles besoin de scopes elles aussi ? Oui, idéalement. Les clés API à scopes vous donnent le moindre privilège sans tout le poids d'OAuth, de sorte qu'une intégration serveur à serveur qui ne fait que lire des données détient une clé qui ne peut ni écrire ni supprimer. C'est la façon la plus pratique de livrer un système basé sur des clés sûr avant de construire OAuth.
Pour aller plus loin
- RFC 6749, The OAuth 2.0 Authorization Framework. La spécification qui définit les flux, jetons et rôles d'OAuth 2.0.
- RFC 6750, Bearer Token Usage. Comment les jetons porteurs sont envoyés et validés, y compris la forme de l'en-tête
Authorization. - MDN : l'en-tête Authorization. Une référence claire sur la façon dont les identifiants voyagent dans une requête HTTP.
- OWASP API Security Project. Les défaillances courantes d'authentification et d'autorisation qui apparaissent dans de vraies API.
En bref
L'authentification est le premier code qu'un partenaire écrit contre votre API, donc c'est votre première impression en code et l'endroit qu'une revue de sécurité examinera le plus durement. Choisissez les clés API pour les intégrations serveur à serveur et à compte unique, OAuth pour les applications agissant au nom des utilisateurs, et prenez en charge les deux quand vous le pouvez, en commençant par des clés API à scopes si vous devez en choisir un. Concevez les scopes autour de cas d'usage réels, appliquez-les côté serveur, et ne vous contentez jamais d'un seul scope tout-puissant.
Documentez les durées de vie des jetons et le rafraîchissement avec des chiffres concrets pour que les partenaires rafraîchissent selon un calendrier plutôt que de découvrir l'expiration en production. Évitez ensuite les incidents prévisibles : clés dans le contrôle de version, jetons qui n'expirent jamais, secrets dans les URL, scopes affichés mais non vérifiés, et identifiants sans moyen de révocation. Faites cela correctement et l'authentification cesse d'être l'endroit où vos intégrations butent.
Si vous voulez un regard extérieur sur exactement cela, un Audit Partenaire examine votre API, votre modèle d'authentification et votre préparation pour les partenaires, puis vous remet un plan concret : quoi corriger, quoi documenter, et quels partenaires approcher une fois qu'un ingénieur peut s'authentifier contre vous en quelques minutes.