Aller au contenu principal

Sécuriser les serveurs MCP : OAuth, liaison d'audience et le député confus

Avancé
What you'll learn
  • Comprendre pourquoi un serveur MCP distant (HTTP) est un serveur de ressources OAuth 2.1, et pas seulement un point d'accès à clé API
  • Suivre le handshake de découverte : 401 → Protected Resource Metadata → Authorization Server Metadata → jeton
  • Expliquer la liaison d'audience des jetons (RFC 8707) et pourquoi elle empêche le jeton d'un service de fonctionner sur un autre
  • Nommer le piège du député confus et l'unique règle qui le referme : ne jamais transférer le jeton d'un client vers une API en amont
  • Appliquer une courte liste de durcissement avant d'exposer un serveur MCP sur Internet

MCP est passé de curiosité à la manière par défaut dont les agents atteignent les outils — ce qui signifie que les serveurs MCP se trouvent désormais devant des données réelles et des actions réelles. Un serveur local que vous lancez via STDIO fait confiance à son environnement : il lit les identifiants depuis les variables d'environnement et il n'y a aucune frontière réseau à défendre. Dès l'instant où vous rendez ce même serveur distant (HTTP), quiconque peut atteindre l'URL peut tenter de l'appeler. Cela le transforme en un problème d'autorisation, et la spécification MCP y répond avec OAuth 2.1 — pas avec un schéma de clé API sur mesure.

Cette page concerne le cas distant. Si votre serveur est uniquement STDIO, la spécification dit explicitement de ne pas suivre le flux OAuth — récupérez les identifiants depuis l'environnement et passez à autre chose.

Les trois rôles

OAuth découpe le problème en trois parties. MCP s'y projette proprement :

Qui est qui dans un flux OAuth MCP
Appuyez sur Entrée ou Espace pour retourner la carte. Utilisez les flèches gauche et droite pour naviguer entre les cartes.Terme affiché.
1 / 3

Le glissement mental clé : le serveur MCP ne gère jamais lui-même la connexion. Il ne fait que valider des jetons émis par quelqu'un d'autre. C'est cette séparation qui vous permet de placer un fournisseur d'identité prêt à l'emploi devant un serveur que vous avez écrit.

Le handshake de découverte

Un client ne devrait pas avoir besoin d'être préconfiguré avec l'endroit où s'authentifier. MCP rend la découverte automatique, pilotée par un 401 :

Guided walkthrough1 of 6
  1. La toute première requête part à nu. Le serveur la rejette avec HTTP 401 Unauthorized et un en-tête WWW-Authenticate pointant vers son URL de resource-metadata.

Remarquez qu'il n'y a aucune config d'authentification codée en dur du côté client — le 401 amorce tout. C'est tout l'intérêt : un agent peut se connecter à un serveur qu'il n'a jamais vu et déterminer comment s'authentifier.

Liaison d'audience : la règle porteuse

Voici le mode de défaillance que la liaison d'audience existe pour empêcher. Disons qu'un utilisateur possède un jeton émis pour calendar.example.com. Un serveur MCP malveillant (ou simplement négligent) à evil.example.com trompe le client pour qu'il lui envoie ce jeton. Si evil l'accepte, il peut désormais se retourner et appeler l'API du calendrier en tant que l'utilisateur. Le jeton d'un service a fonctionné sur un autre. La frontière de sécurité d'OAuth vient de s'effondrer.

Le correctif, ce sont les Resource Indicators (RFC 8707) :

Guided walkthrough1 of 3
  1. À la fois sur la requête d'autorisation et sur la requête de jeton, le client DOIT inclure un paramètre resource fixé à l'URI canonique du serveur MCP qu'il compte appeler — par ex. resource=https://mcp.example.com. Il l'envoie même s'il n'est pas sûr que l'AS le prenne en charge.

Paramètre resource sur la requête d'autorisation (encodé en URL)

&resource=https%3A%2F%2Fmcp.example.com

Les URI canoniques sont strictes : https://mcp.example.com et https://mcp.example.com:8443/mcp sont valides ; mcp.example.com (sans schéma) et https://mcp.example.com#frag (fragment) ne le sont pas. Préférez la forme sans barre oblique finale pour l'interopérabilité.

Le député confus : ne jamais transférer le jeton

C'est l'erreur qui transforme un serveur MCP bien intentionné en proxy pour un attaquant. C'est le même problème du député confus issu de la sécurité des agents, affûté en une règle concrète.

Un serveur MCP a souvent besoin d'appeler une API en amont (GitHub, un service de base de données, un autre SaaS). La tentation est de prendre le jeton que le client vous a remis et de le transférer en amont. Ne le faites pas. La spécification est catégorique : le serveur MCP NE DOIT PAS transférer le jeton qu'il a reçu du client.

Pourquoi c'est dangereux : le jeton du client a été émis pour votre serveur comme audience. Si vous le transférez, l'API en amont peut lui faire confiance comme s'il venait de vous, ou supposer que vous l'avez déjà validé — et voilà qu'un jeton limité à un saut effectue du travail deux sauts plus loin, hors du modèle de consentement de qui que ce soit.

Watch out
  • Si votre serveur MCP appelle une API en amont, il agit comme un client OAuth DISTINCT vis-à-vis de cette API et obtient son PROPRE jeton auprès du serveur d'autorisation en amont. Deux jetons indépendants, deux audiences indépendantes. Le jeton du client s'arrête à votre porte.

Une liste de durcissement pré-vol

Avant qu'un serveur MCP distant touche l'Internet public :

Guided walkthrough1 of 7
  1. Tous les points d'accès de l'AS DOIVENT être en HTTPS. Les redirect URIs DOIVENT être en HTTPS ou localhost — rien d'autre.

Vérifiez vos acquis

Vérifiez vos acquis

0/4
  1. Un serveur MCP distant reçoit une requête sans jeton d'accès. Que la spécification lui impose-t-elle de faire en premier ?
  2. Contre quoi la liaison d'audience des jetons (RFC 8707) protège-t-elle ?
  3. Votre serveur MCP doit appeler une API GitHub en amont. Que doit-il faire du jeton d'accès que le client lui a envoyé ?
  4. Pour un serveur MCP STDIO (local), comment la spécification dit-elle de gérer les identifiants ?

Sources et lectures complémentaires