Sécurité des API pour le CTO : identité, passerelle et jetons, sans faire confiance aveuglément
Par Dorian Chávez · fondateur de Hábil et architecte d'intégration ·
Quand revalider le jeton derrière la passerelle, comment les API s'appellent entre elles, introspection ou validation locale, déconnexion et durée d'un jeton.
Une architecture de sécurité des API fréquente aujourd'hui comporte trois éléments : un fournisseur d'identité qui émet les jetons —Keycloak, Microsoft Entra ID, Okta ou un autre—, une passerelle (gateway) qui reçoit tout le trafic —APISIX, Kong, Apigee, Azure API Management ou une autre— et OAuth 2.0 comme langage dans lequel les permissions se demandent et se présentent. C'est une bonne architecture. Le problème apparaît dans les questions que personne n'a écrites lors de sa conception : le service situé derrière la passerelle revérifie-t-il le jeton ? Que se passe-t-il quand une API en appelle une autre ? Si l'utilisateur ferme sa session, son jeton cesse-t-il d'être valide ? Combien de temps un jeton doit-il durer ?
Cet article répond à ces questions pour celui ou celle qui doit signer l'architecture : le CTO d'une banque, d'une fintech, d'un assureur, d'une chaîne de distribution ou de toute entreprise réglementée. Chaque réponse vient avec sa condition, car en sécurité il n'y a presque jamais de « toujours ».
Trois types de route, trois niveaux de confiance
Avant de parler de jetons, il convient de classer chaque route de l'API :
| Type de route | À quoi elle sert | Ce qu'elle prouve | Ce qu'elle ne prouve pas |
|---|---|---|---|
| Publique | Catalogues, informations générales, état du service | Rien | Qui appelle |
| Avec clé d'API | Identifier un consommateur, mesurer et limiter son usage | Que l'appelant possède la clé | Qui est la personne, ce qu'elle a consenti ni si la clé a été volée |
| Avec jeton OAuth | Accès avec permissions, au nom d'un système ou d'une personne | Avec un access token OAuth configuré pour cette API : permet de vérifier les attributs que le profil et le fournisseur émettent —par exemple, émetteur, audience, validité et permissions— par validation JWT ou par introspection | Que la personne est toujours autorisée en ce moment, si le jeton est long |
Une clé d'API identifie, mais elle n'autorise pas bien : elle ne porte ni permissions fines, ni destinataire, ni expiration standard, ni délégation [1][2]. Elle convient à la consommation simple, à la mesure et aux quotas. Pour une intégration entre entreprises (B2B) avec des données sensibles, il convient d'utiliser OAuth 2.0 avec identifiants de client (client credentials) : le système partenaire obtient par API un jeton de courte durée, aux permissions limitées et destiné à votre API [3][4]. Cette voie s'applique lorsque le système agit pour son propre compte ou dans le cadre d'un accord préalable ; elle ne remplace pas le consentement d'une personne. Si vous conservez des clés d'API : une par consommateur et par environnement, stockée comme un secret, soumise à rotation et jamais dans l'URL, car les URL sont consignées dans les journaux de la passerelle, des proxies et des outils de supervision, où toute personne ayant accès peut les lire [2].
Le service derrière la passerelle doit-il vérifier le jeton ?
C'est la question qui suscite le plus de discussions, et la réponse courte est : se trouver derrière la passerelle ne donne pas confiance en soi. C'est ce que dit le cadre de confiance zéro du NIST : l'emplacement sur le réseau n'implique pas la confiance, et la zone de confiance implicite doit être la plus petite possible [5].
La réponse complète sépare deux choses que l'on confond souvent :
- Valider le jeton (est-il authentique, mon fournisseur l'a-t-il émis, m'est-il destiné, est-il toujours valide ?).
- Autoriser l'opération (cette personne ou ce système peut-il lire ce compte, cette police, cette commande ?).
La seconde, l'autorisation fine sur l'objet, doit être évaluée là où sont disponibles la règle métier et la relation avec l'objet : normalement dans le service ou dans un composant de politique intégré à celui-ci. La passerelle peut la compléter par des contrôles larges, mais elle ne remplace pas cette règle. Une permission générique comme « lire les paiements » ne décide pas si quelqu'un peut lire le paiement d'un autre client. Cette erreur a un nom et c'est la première de la liste des risques des API de l'OWASP [6][7].
La première peut être déléguée à la passerelle, mais seulement si toutes ces conditions sont réunies [5][8][9] :
- Le service n'est joignable par aucun autre chemin que la passerelle : ni depuis un autre réseau, ni depuis un autre service voisin, ni par une route d'administration.
- Le canal entre la passerelle et le service est authentifié, par exemple avec du TLS mutuel.
- La passerelle supprime tout en-tête d'identité qui arrive de l'extérieur et pose le sien, signé (par exemple un jeton interne) ou sur un canal authentifié, de sorte que le service puisse vérifier qu'il provient de la passerelle.
- La configuration des routes est inventoriée, testée et échoue en mode fermé : une route sans règle ne reste pas ouverte.
Si une condition n'est pas remplie, documentez un autre point d'application de la politique qui valide de façon vérifiable l'identité de l'appelant et le contexte ; s'il n'en existe pas, le service devra le faire. Et il y a des cas où il convient qu'il le valide même si les quatre sont réunies : lorsqu'il manipule de l'argent ou des données personnelles, lorsqu'il décide à partir de données du jeton, ou lorsqu'il sert plusieurs clients ou domaines.
Un détail de configuration qui vaut de l'or : dans certaines passerelles, les plugins qui valident les clés d'API ou les JWT transmettent les informations d'authentification d'origine au service situé derrière sauf configuration contraire, et celui d'OpenID Connect, avec bearer_only à false, n'exige pas strictement un jeton porteur [10][11]. Ce sont les valeurs documentées dans APISIX 3.19 [fournisseur] ; confirmez la version installée et la configuration effective. Revoir ces valeurs par défaut fait partie de l'architecture, ce n'est pas un détail.
Quand une API en appelle une autre
Au sein de l'architecture, un service a besoin d'en appeler un autre. Il existe cinq modèles fréquents, et chacune sert à quelque chose de différent [12][13][14] :
| Y a-t-il un utilisateur derrière ? | Modèle | Utilisez-le lorsque | Risque en cas de mauvais usage |
|---|---|---|---|
| Oui | Transmettre le jeton de l'utilisateur | Le service de destination est déclaré comme destinataire du jeton | L'intermédiaire détient un jeton qui sert à d'autres services |
| Oui | Échanger le jeton (token exchange, RFC 8693) | La destination a besoin de savoir qui est l'utilisateur, mais avec un jeton propre, réduit et destiné à elle | Que l'échange permette de demander n'importe quelle permission pour n'importe quelle destination |
| Non | Identifiants du service lui-même | Travail technique, traitements par lots, événements, rapprochement : il n'y a pas d'utilisateur derrière | Attribuer à un utilisateur une action effectuée par le système |
| Oui | Jeton interne de courte durée | La passerelle remplace le jeton externe par un jeton interne, valable seulement à l'intérieur | Créer sans le vouloir un second fournisseur d'identité sans gouvernance |
| Non | TLS mutuel seul entre services | Il suffit de savoir quel service appelle | Le certificat prouve le service, pas la permission de l'utilisateur |
Une règle qui réduit le risque de réutilisation indue : chaque service vérifie que le jeton lui était destiné. Le champ qui l'indique s'appelle l'audience (aud), et si le service n'y figure pas, le jeton est rejeté [15][16] ; pour restreindre la destination lors de la demande, il existe les indicateurs de ressource (RFC 8707) [30]. On évite ainsi l'erreur de la « retransmission aveugle » (token passthrough) et sa conséquence la plus connue, le confused deputy : un service qui, avec un jeton qui n'est pas le sien, fait quelque chose que l'utilisateur n'a jamais autorisé. Par exemple, un service de rapports qui reçoit un jeton émis pour le service de paiements et qui, avec lui, finit par pouvoir exécuter des paiements.
Pour la chaîne « A appelle B au nom de l'utilisateur », le modèle recommandé est l'échange de jetons : A échange le jeton reçu contre un nouveau, destiné à B et avec moins de permissions [12]. Dans Keycloak, la fonction standard V2 est activée par défaut, mais le client demandeur doit être confidentiel et avoir activé Standard token exchange ; l'échange standard opère entre clients d'un même realm [17]. Et le NIST propose quelque chose de similaire pour les microservices : remplacer le jeton externe à l'entrée par un jeton interne de courte durée, et le vérifier à chaque saut [8].
Faire confiance au jeton ou interroger le fournisseur ?
Il existe deux façons de savoir si un jeton est bon :
| Méthode | Convient lorsque | Avantage | Limite |
|---|---|---|---|
| Validation locale du JWT (signature avec les clés publiques du fournisseur, émetteur, audience, expiration) | Fort volume, faible latence | Ne dépend pas de la disponibilité du fournisseur à chaque requête | Ne sait pas si le jeton a été révoqué après son émission |
| Introspection (RFC 7662) : interroger le fournisseur | Jetons opaques, ou actions où l'état actuel compte | Répond si le jeton est encore actif maintenant | Ajoute de la latence et une dépendance au fournisseur |
| Mixte | API réglementées à fort volume | Validation locale pour l'ordinaire, introspection pour le critique | Il faut décider et documenter ce qui est « critique » |
Valider localement ne se résume pas à « la signature est passée » : il faut fixer l'émetteur attendu, n'accepter que les algorithmes prévus, vérifier l'audience, l'expiration et les permissions, et obtenir les clés auprès d'une source fiable, car le fournisseur les renouvelle : le service met en cache les clés publiques et, lorsqu'arrive un jeton signé avec une clé qu'il ne connaît pas, il les redemande au lieu de le rejeter ou de l'accepter à l'aveugle [18][19]. Et un coût que le CTO signe : avec l'introspection à chaque requête, le fournisseur d'identité se retrouve sur le chemin critique de toutes les opérations ; s'il tombe ou ralentit, tout tombe ou ralentit. Et si l'on met en cache le résultat d'une introspection, la durée du cache ne peut pas dépasser la fenêtre de révocation que l'entreprise accepte : un cache de cinq minutes contredit une promesse de révocation « immédiate ».
Fermer la session n'éteint pas les jetons déjà émis
Un effet opérationnel important, qui surprend souvent un comité de sécurité : lorsqu'un utilisateur ferme sa session, l'access token qu'il possédait reste valide jusqu'à son expiration, pour tout service qui le valide localement. Les mécanismes de déconnexion d'OpenID Connect terminent la session et préviennent les applications, mais n'invalident pas les access tokens qui circulent déjà [20][21] ; la documentation de Keycloak l'avertit explicitement [17].
C'est pourquoi la durée de vie se conçoit en couches :
- Des access tokens courts, pour que la fenêtre d'exposition soit petite.
- Des refresh tokens révocables, liés au client et, dans les applications publiques, avec rotation [3].
- L'introspection dans les opérations où l'état actuel compte : virements, changements de bénéficiaire, téléchargements massifs, actions d'administration.
- La révocation (RFC 7009) lorsque le fournisseur la prend en charge [22].
- Des événements de révocation entre systèmes (OpenID CAEP), qui sont déjà un standard final ; leur prise en charge chez les fournisseurs est encore inégale [23].
Combien de temps un jeton doit-il durer ?
Il n'existe aucune durée « standard » dans aucune norme. OAuth laisse la durée de vie du jeton au fournisseur [4] ; le standard des jetons porteurs recommande une heure ou moins [24] ; et le profil de sécurité de l'open banking (FAPI 2.0) demande des jetons courts sans fixer de chiffre [25]. Ce qui existe, ce sont des plages initiales de conception —critère éditorial, pas une norme— ; ajustez-les à l'exposition, à la fenêtre de révocation, à la réauthentification et à la disponibilité du fournisseur :
| Jeton | Point de départ | Commentaire |
|---|---|---|
| Access token d'une personne | 5 minutes ; de 1 à 5 pour les paiements et l'administration | Seulement si le refresh token est en rotation et lié au client ; sinon, une durée un peu plus longue convient, compensée par l'introspection sur le critique |
| Access token entre entreprises (identifiants de client) | De 5 à 15 minutes | Il se renouvelle en authentifiant à nouveau le système |
| Refresh token | Ce que dure la session : inactivité et maximum | Ne pas renouveler en silence une session inactive |
| Jeton « offline » (de longue durée) | Seulement comme exception approuvée | Avec un maximum explicite et la révocation |
Les valeurs d'usine de Keycloak [fournisseur] vont dans ce sens. Nous les avons vérifiées directement dans son code source (branche principale consultée le 6 octobre 2026), car la documentation ne les publie pas toutes [26]. Ce sont des chiffres du fournisseur et ils peuvent changer d'une version à l'autre :
| Réglage de Keycloak | Valeur par défaut |
|---|---|
| Durée de vie de l'access token | 5 minutes (1 minute dans le domaine d'administration « master ») |
| Session : inactivité | 30 minutes |
| Session : maximum | 10 heures |
| Session offline : inactivité | 30 jours (son maximum est désactivé par défaut) |
Dans Keycloak, le refresh token d'une session normale vit aussi longtemps que la session le permet. Avant de vous fier à ces chiffres, vérifiez ceux de votre installation : les réglages par client et les imports les modifient.
Quand OpenID Connect est-il nécessaire ?
- OAuth 2.0 suffit lorsque ce que l'on protège est l'accès d'une application ou d'un système à une API : intégrations entre entreprises, processus internes, permissions par portée [4].
- OpenID Connect convient lorsque l'application a besoin d'une identité authentifiée interopérable, de claims d'authentification ou d'une authentification unique (aussi niveau d'authentification, déconnexion et réauthentification pour les actions sensibles) [27]. OAuth seul ne standardise pas cette identité : OpenID Connect est la couche d'identité au-dessus d'OAuth.
- Une erreur fréquente : utiliser l'ID token d'OpenID Connect pour appeler une API. L'ID token est destiné à l'application qui a ouvert la session ; c'est l'access token que l'on envoie à l'API [27].
En open banking, la barre monte
Si votre API relève de l'open banking ou des données financières, le profil FAPI 2.0 (standard final) relève la barre : jetons liés à celui qui les utilise —avec TLS mutuel ou DPoP—, authentification forte du client et paramètres de la requête protégés [25][28][29]. Il n'est pas obligatoire pour toutes les API ni une obligation mexicaine en soi : il peut être une référence technique utile pour les API à forte valeur lorsque le cadre applicable, un contrat ou la politique de risque l'adoptent, et il ne remplace pas l'évaluation des obligations réglementaires applicables.
Par où commencer
- Classez vos routes en publiques, avec clé d'API et avec jeton, et vérifiez que chacune est là où elle doit être.
- Décidez, service par service, qui valide le jeton, avec les quatre conditions ci-dessus par écrit.
- Vérifiez l'audience dans chaque service et éliminez la retransmission aveugle des jetons.
- Révisez les valeurs par défaut de votre fournisseur d'identité et de votre passerelle.
- Définissez votre fenêtre de révocation par type d'opération, et ajustez les durées et l'introspection en conséquence.
Combien de vos routes résisteraient aujourd'hui à cette revue ? La première conversation de diagnostic est sans frais : vous repartez avec la carte de vos routes par niveau de confiance et les écarts à traiter en premier. Écrivez-nous sur WhatsApp.
Références
- OWASP, REST Security Cheat Sheet (API keys). https://cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html
- OWASP, OAuth2 Cheat Sheet. https://cheatsheetseries.owasp.org/cheatsheets/OAuth2_Cheat_Sheet.html
- IETF, RFC 9700, Best Current Practice for OAuth 2.0 Security (2025). https://www.rfc-editor.org/rfc/rfc9700.html
- IETF, RFC 6749, The OAuth 2.0 Authorization Framework, §4.4 client credentials. https://www.rfc-editor.org/rfc/rfc6749.html
- NIST, SP 800-207, Zero Trust Architecture. https://csrc.nist.gov/pubs/sp/800/207/final
- OWASP, API Security Top 10 2023 (API1: Broken Object Level Authorization). https://api-security.owasp.org/editions/2023/en/0xa1-broken-object-level-authorization/
- OWASP, Authorization Cheat Sheet. https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html
- NIST, SP 800-207A, A Zero Trust Architecture Model for Access Control in Cloud-Native Applications. https://csrc.nist.gov/pubs/sp/800/207/a/final
- NIST, SP 800-204, Security Strategies for Microservices-based Application Systems. https://csrc.nist.gov/pubs/sp/800/204/final
- Apache APISIX, plugins
key-authetjwt-auth(hide_credentials). https://apisix.apache.org/docs/apisix/plugins/key-auth/ · https://apisix.apache.org/docs/apisix/plugins/jwt-auth/ - Apache APISIX, plugin
openid-connect(bearer_only, introspection, JWKS). https://apisix.apache.org/docs/apisix/plugins/openid-connect/ - IETF, RFC 8693, OAuth 2.0 Token Exchange. https://www.rfc-editor.org/rfc/rfc8693.html
- OWASP, Identity Propagation Patterns Cheat Sheet. https://cheatsheetseries.owasp.org/cheatsheets/Identity_Propagation_Patterns_Cheat_Sheet.html
- IETF, RFC 8705, OAuth 2.0 Mutual-TLS Client Authentication. https://www.rfc-editor.org/rfc/rfc8705.html
- IETF, RFC 7519, JSON Web Token, §4.1.3 (aud). https://www.rfc-editor.org/rfc/rfc7519.html
- IETF, RFC 9068, JWT Profile for OAuth 2.0 Access Tokens. https://www.rfc-editor.org/rfc/rfc9068.html
- Keycloak, Server Administration Guide et Securing Applications Guide (audience, échange de jetons, sessions). https://www.keycloak.org/securing-apps/token-exchange · https://www.keycloak.org/documentation
- OWASP, JSON Web Token Cheat Sheet. https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_Cheat_Sheet.html
- IETF, RFC 7662, OAuth 2.0 Token Introspection. https://www.rfc-editor.org/rfc/rfc7662.html
- OpenID, Back-Channel Logout 1.0. https://openid.net/specs/openid-connect-backchannel-1_0.html
- OpenID, RP-Initiated Logout 1.0. https://openid.net/specs/openid-connect-rpinitiated-1_0.html
- IETF, RFC 7009, OAuth 2.0 Token Revocation. https://www.rfc-editor.org/rfc/rfc7009.html
- OpenID, CAEP 1.0 (Continuous Access Evaluation Profile). https://openid.net/specs/openid-caep-1_0-final.html
- IETF, RFC 6750, Bearer Token Usage, §5.3. https://www.rfc-editor.org/rfc/rfc6750.html
- OpenID, FAPI 2.0 Security Profile (final). https://openid.net/specs/fapi-security-profile-2_0-final.html
- Keycloak [fournisseur], code source :
Constants.javaetApplianceBootstrap.java(valeurs par défaut), branche principale consultée le 6 octobre 2026 ; liens vers le dernier commit de chaque fichier à cette date. https://github.com/keycloak/keycloak/blob/55e0a796c7d397027c766efcad1ba47706ba8f72/server-spi-private/src/main/java/org/keycloak/models/Constants.java · https://github.com/keycloak/keycloak/blob/3575af2b5bc19fa16d3f6caf39ad1fc869c3fdda/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java - OpenID, OpenID Connect Core 1.0. https://openid.net/specs/openid-connect-core-1_0.html
- IETF, RFC 9449, OAuth 2.0 Demonstrating Proof of Possession (DPoP). https://www.rfc-editor.org/rfc/rfc9449.html
- OpenID, FAPI 2.0 Message Signing (final). https://openid.net/specs/fapi-message-signing-2_0-final.html
- IETF, RFC 8707, Resource Indicators for OAuth 2.0. https://www.rfc-editor.org/rfc/rfc8707.html
- Maîtriser les accès →
- Des API prêtes pour les agents d'IA →
- SSO avec SAML 2.0 dans les Services Financiers : Implémentation Enterprise →
Votre activité fait face à ces défis ?
Vous préférez l'e-mail ? Écrivez-nous à hola@habil.mx