Sécurité17 min

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 :

Trois types de route, trois niveaux de confiance
Type de routeÀ quoi elle sertCe qu'elle prouveCe qu'elle ne prouve pas
PubliqueCatalogues, informations générales, état du serviceRienQui appelle
Avec clé d'APIIdentifier un consommateur, mesurer et limiter son usageQue 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 OAuthAccès avec permissions, au nom d'un système ou d'une personneAvec 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 introspectionQue 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] :

  1. 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.
  2. Le canal entre la passerelle et le service est authentifié, par exemple avec du TLS mutuel.
  3. 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.
  4. 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] :

Quand une API en appelle une autre
Y a-t-il un utilisateur derrière ?ModèleUtilisez-le lorsqueRisque en cas de mauvais usage
OuiTransmettre le jeton de l'utilisateurLe service de destination est déclaré comme destinataire du jetonL'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é à elleQue l'échange permette de demander n'importe quelle permission pour n'importe quelle destination
NonIdentifiants du service lui-mêmeTravail technique, traitements par lots, événements, rapprochement : il n'y a pas d'utilisateur derrièreAttribuer à un utilisateur une action effectuée par le système
OuiJeton interne de courte duréeLa passerelle remplace le jeton externe par un jeton interne, valable seulement à l'intérieurCréer sans le vouloir un second fournisseur d'identité sans gouvernance
NonTLS mutuel seul entre servicesIl suffit de savoir quel service appelleLe 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 :

Faire confiance au jeton ou interroger le fournisseur ?
MéthodeConvient lorsqueAvantageLimite
Validation locale du JWT (signature avec les clés publiques du fournisseur, émetteur, audience, expiration)Fort volume, faible latenceNe dépend pas de la disponibilité du fournisseur à chaque requêteNe sait pas si le jeton a été révoqué après son émission
Introspection (RFC 7662) : interroger le fournisseurJetons opaques, ou actions où l'état actuel compteRépond si le jeton est encore actif maintenantAjoute de la latence et une dépendance au fournisseur
MixteAPI réglementées à fort volumeValidation locale pour l'ordinaire, introspection pour le critiqueIl 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 :

  1. Des access tokens courts, pour que la fenêtre d'exposition soit petite.
  2. Des refresh tokens révocables, liés au client et, dans les applications publiques, avec rotation [3].
  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.
  4. La révocation (RFC 7009) lorsque le fournisseur la prend en charge [22].
  5. 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 :

Combien de temps un jeton doit-il durer ?
JetonPoint de départCommentaire
Access token d'une personne5 minutes ; de 1 à 5 pour les paiements et l'administrationSeulement 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 minutesIl se renouvelle en authentifiant à nouveau le système
Refresh tokenCe que dure la session : inactivité et maximumNe pas renouveler en silence une session inactive
Jeton « offline » (de longue durée)Seulement comme exception approuvéeAvec 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 :

Combien de temps un jeton doit-il durer ?
Réglage de KeycloakValeur par défaut
Durée de vie de l'access token5 minutes (1 minute dans le domaine d'administration « master »)
Session : inactivité30 minutes
Session : maximum10 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

  1. Classez vos routes en publiques, avec clé d'API et avec jeton, et vérifiez que chacune est là où elle doit être.
  2. Décidez, service par service, qui valide le jeton, avec les quatre conditions ci-dessus par écrit.
  3. Vérifiez l'audience dans chaque service et éliminez la retransmission aveugle des jetons.
  4. Révisez les valeurs par défaut de votre fournisseur d'identité et de votre passerelle.
  5. 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

  1. OWASP, REST Security Cheat Sheet (API keys). https://cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html
  2. OWASP, OAuth2 Cheat Sheet. https://cheatsheetseries.owasp.org/cheatsheets/OAuth2_Cheat_Sheet.html
  3. IETF, RFC 9700, Best Current Practice for OAuth 2.0 Security (2025). https://www.rfc-editor.org/rfc/rfc9700.html
  4. IETF, RFC 6749, The OAuth 2.0 Authorization Framework, §4.4 client credentials. https://www.rfc-editor.org/rfc/rfc6749.html
  5. NIST, SP 800-207, Zero Trust Architecture. https://csrc.nist.gov/pubs/sp/800/207/final
  6. OWASP, API Security Top 10 2023 (API1: Broken Object Level Authorization). https://api-security.owasp.org/editions/2023/en/0xa1-broken-object-level-authorization/
  7. OWASP, Authorization Cheat Sheet. https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html
  8. 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
  9. NIST, SP 800-204, Security Strategies for Microservices-based Application Systems. https://csrc.nist.gov/pubs/sp/800/204/final
  10. Apache APISIX, plugins key-auth et jwt-auth (hide_credentials). https://apisix.apache.org/docs/apisix/plugins/key-auth/ · https://apisix.apache.org/docs/apisix/plugins/jwt-auth/
  11. Apache APISIX, plugin openid-connect (bearer_only, introspection, JWKS). https://apisix.apache.org/docs/apisix/plugins/openid-connect/
  12. IETF, RFC 8693, OAuth 2.0 Token Exchange. https://www.rfc-editor.org/rfc/rfc8693.html
  13. OWASP, Identity Propagation Patterns Cheat Sheet. https://cheatsheetseries.owasp.org/cheatsheets/Identity_Propagation_Patterns_Cheat_Sheet.html
  14. IETF, RFC 8705, OAuth 2.0 Mutual-TLS Client Authentication. https://www.rfc-editor.org/rfc/rfc8705.html
  15. IETF, RFC 7519, JSON Web Token, §4.1.3 (aud). https://www.rfc-editor.org/rfc/rfc7519.html
  16. IETF, RFC 9068, JWT Profile for OAuth 2.0 Access Tokens. https://www.rfc-editor.org/rfc/rfc9068.html
  17. 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
  18. OWASP, JSON Web Token Cheat Sheet. https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_Cheat_Sheet.html
  19. IETF, RFC 7662, OAuth 2.0 Token Introspection. https://www.rfc-editor.org/rfc/rfc7662.html
  20. OpenID, Back-Channel Logout 1.0. https://openid.net/specs/openid-connect-backchannel-1_0.html
  21. OpenID, RP-Initiated Logout 1.0. https://openid.net/specs/openid-connect-rpinitiated-1_0.html
  22. IETF, RFC 7009, OAuth 2.0 Token Revocation. https://www.rfc-editor.org/rfc/rfc7009.html
  23. OpenID, CAEP 1.0 (Continuous Access Evaluation Profile). https://openid.net/specs/openid-caep-1_0-final.html
  24. IETF, RFC 6750, Bearer Token Usage, §5.3. https://www.rfc-editor.org/rfc/rfc6750.html
  25. OpenID, FAPI 2.0 Security Profile (final). https://openid.net/specs/fapi-security-profile-2_0-final.html
  26. Keycloak [fournisseur], code source : Constants.java et ApplianceBootstrap.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
  27. OpenID, OpenID Connect Core 1.0. https://openid.net/specs/openid-connect-core-1_0.html
  28. IETF, RFC 9449, OAuth 2.0 Demonstrating Proof of Possession (DPoP). https://www.rfc-editor.org/rfc/rfc9449.html
  29. OpenID, FAPI 2.0 Message Signing (final). https://openid.net/specs/fapi-message-signing-2_0-final.html
  30. IETF, RFC 8707, Resource Indicators for OAuth 2.0. https://www.rfc-editor.org/rfc/rfc8707.html