MCP OAuth 2.1 avec PKCE : sécurisez votre serveur d'agents en 7 étapes
La spécification MCP du 15/03/2026 fait d'OAuth 2.1 + PKCE la norme d'autorisation pour les serveurs d'agents. Sept étapes pour l'expédition : métadonnées PRM, enregistrement dynamique des clients, conception de la portée et validation des jetons avec du code.
La spécification MCP du 15/03/2026 verrouille OAuth 2.1 avec PKCE comme norme d'autorisation pour serveurs MCP distants. Les clés API dans les variables d'environnement fonctionnent toujours dès le premier jour, mais le registre, Claude Desktop, Cursor, VS Code Copilot et Windsurf préfèrent tous les serveurs soutenus par OAuth lorsque les utilisateurs recherchez les intégrations. Si votre serveur demande toujours un support de longue durée dans un fichier de configuration, vous laissent une part de la distribution sur la table.
Le plus difficile n’est pas OAuth lui-même ; ce sont les cinq petites spécifications que compose le flux d'authentification MCP ensemble : OAuth 2.1 (RFC 9700), PKCE (RFC 7636), Dynamic Client Registration (RFC 7591), Indicateurs de ressources (RFC 8707) et métadonnées de ressources protégées. Chacun est petit ; le câblage C'est là que les équipes restent bloquées. Voici le chemin, dans l'ordre.
Étape 1 : Servir un document de métadonnées de ressources protégées
Le fichier PRM indique aux clients où se trouve votre serveur d'autorisation, quelles étendues vous acceptez et quelles
identifiant de ressource à mettre dans le aud réclamer. Hébergez-le à
/.well-known/oauth-protected-resource sur la même origine que votre point de terminaison MCP :
La authorization_servers list est le saut de découverte. Les clients récupèrent votre PMR,
suivez la première entrée du document de métadonnées AS et créez l'URL d'autorisation à partir de là.
Gardez la liste à une seule entrée, sauf si vous dirigez une fédération ; plusieurs émetteurs confondent le client et
rien dans la spécification ne l'exige.
Étape 2 : Publier les métadonnées du serveur d'autorisation
Votre fournisseur d'identité (Auth0, Okta, Clerk, Cloudflare Access ou Hydra auto-hébergé) sert
les métadonnées AS à /.well-known/oauth-authorization-server. Les clients MCP le consomment
pour connaître les points de terminaison d'autorisation et de jeton, les types d'octroi pris en charge et l'emplacement JWKS
pour la vérification des jetons :
Trois champs exigés par la spécification : code_challenge_methods_supported doit inclure
S256; grant_types_supported doit inclure
authorization_code et refresh_token;
registration_endpoint doit être présent si vous prenez en charge des clients dynamiques. Quelqu'un me manque
et Claude Desktop signalera le serveur comme non conforme lors de l'installation.
Étape 3 : Générer une paire PKCE sur le client
PKCE est constitué de 20 lignes de code client et il tue la classe d'interception de code d'autorisation de attaque. Générez 32 octets aléatoires, encodez-les en base64url dans un vérificateur, SHA-256 le vérificateur dans un défi, et envoyez le défi avec la demande d'autorisation :
La resource Le paramètre (RFC 8707) est celui qui manque à la plupart des implémentations. Sans
dessus, un jeton créé pour votre serveur MCP peut être rejoué avec n'importe quelle autre API qui fait confiance au
même émetteur ; avec lui, le aud la réclamation épingle le jeton à votre identifiant de ressource
et rien d'autre ne l'accepte.
Étape 4 : Échangez le code contre des jetons
Après la redirection, le client POST le code ainsi que le vérificateur d'origine sur le jeton point final. Le serveur d'autorisation recalcule le SHA-256 du vérificateur et le compare à le défi stocké ; s'ils correspondent, vous obtenez un jeton d'accès :
Stockez le jeton d'actualisation dans un stockage sécurisé (porte-clés, Windows Credential Manager, Linux libsecret) et supprimez le vérificateur du stockage de session dès que l'échange réussit. Accès les jetons durent 5 à 60 minutes ; les jetons d'actualisation durent plus longtemps mais devraient toujours tourner lors de leur utilisation.
Étape 5 : Vérifiez le jeton du porteur sur chaque demande MCP
Streamable HTTP simplifie la vérification des jetons : chaque requête HTTP porte le
Authorization en-tête, afin que votre serveur MCP le vérifie dans le middleware avant
envoyer l'appel d'outil. Récupérez le JWKS une fois, mettez-le en cache et validez l'émetteur, l'audience et
expiration à chaque appel :
Les trois affirmations qui détectent de vrais bugs : iss épingle l'émetteur ;
aud épingle la ressource (empêche la relecture entre ressources) ;
exp attrape les jetons périmés. N'acceptez pas de jetons sans ceux-ci ; "J'ai validé le
signature » n'est pas la même chose que « J'ai validé les revendications ».
Étape 6 : Gate chaque outil sur les portées déclarées par ses annotations
La conception OAuth 2.1 sans portée vous donne un accès binaire : soit le client peut appeler chaque outil, soit aucun. Le système d'annotation MCP comble cette lacune en permettant à chaque outil de déclarer les portées qu'il besoins. Le gestionnaire lit les annotations et les portées du jeton au moment de l'appel :
Séparez les portées destructives et en lecture seule. Un utilisateur qui a accordé tools:read à
exécuter un rapport hebdomadaire ne devrait pas pouvoir être exécuté send_email du même jeton.
Claude Desktop et Cursor font apparaître les étendues demandées dans l'écran de consentement, de sorte que la séparation fait
l'UX honnête sur ce que le client peut faire.
Étape 7 : Prise en charge de l'enregistrement dynamique des clients
L'enregistrement dynamique du client permet à un client MCP de s'auto-enregistrer sur votre serveur d'autorisation
sans qu'un humain ne remplisse un formulaire. Cursor ou Claude Desktop POST une demande d'inscription,
reçoit un client_id, et exécute le flux OAuth immédiatement :
C'est l'élément qui fait passer votre serveur MCP de "coller une clé API dans un fichier de configuration" à "cliquez sur Connecter dans le curseur et accordez l'accès." Cela vaut le coup si votre serveur est public ; désactivable si vous expédiez uniquement à un petit groupe de clients connus.
Vérifier le flux complet de bout en bout
Une fois les pièces en place, un appel d'outil MCP complet ressemble à n'importe quel autre appel d'outil authentifié par le porteur. Requête HTTP :
Si tu vois 401 avec WWW-Authenticate: Bearer resource_metadata="...",
le client sait où découvrir votre configuration d'authentification et réexécuter le flux. Cet en-tête est le
poignée de main qui permet l'actualisation silencieuse du jeton et la reconnexion après une révocation.
Mettez l'URL PRM dans le WWW-Authenticate en-tête sur chaque réponse 401. Le MCP
spec en fait l'indice de découverte canonique ; les clients qui voient un 401 non annoté se replient
à demander à l'utilisateur une clé API, ce qui est exactement le flux qu'OAuth 2.1 tente de remplacer.
Aide-mémoire pour la conception de la portée
| Portée | Couvertures | Octroi par défaut |
|---|---|---|
tools:read |
Répertorier les outils disponibles, lire les descriptions | Toujours accordé sur consentement |
tools:invoke:safe |
Appels d'outils idempotents en lecture seule (recherches, analyse) | Accordé par consentement de l'utilisateur |
tools:invoke:destructive |
Appels d'outils de mutation (envoyer un e-mail, créer une commande) | Nécessite un consentement explicite par session |
resources:read |
Accès en lecture seule aux ressources exposées | Accordé par modèle de ressource |
prompts:read |
Répertorier et lire les invites définies par le serveur | Accordé sur consentement |
Points clés à retenir
- OAuth 2.1 nécessite PKCE. Ce n’est pas agréable à avoir ; chaque flux de code d'authentification comporte un vérificateur et contester ou il ne respecte pas les spécifications.
-
PMR à
/.well-known/oauth-protected-resourceest le point d'entrée. Les clients découvrent votre configuration d'authentification à partir de cette URL ; ignorez-le et les clients ne peuvent pas se configurer automatiquement. -
Utilisez le
resourceparamètre (RFC 8707). Épingle l'audience symbolique sur votre serveur MCP afin qu'un jeton divulgué ne puisse pas être rejoué avec d'autres API. - Validez l’émetteur, l’audience, l’expiration, la portée. Les contrôles de signature seuls permettent relecture inter-ressources.
-
Divisez les portées destructrices.
tools:read,tools:invoke:safe, ettools:invoke:destructivedonner aux utilisateurs le consentement UX qu’ils attendent des autorisations du système d’exploitation. - L'enregistrement dynamique du client déverrouille les installations sans configuration. Payer le coût de mise en œuvre une fois ; chaque nouveau client MCP en bénéficie pour toujours.
Le serveur MCP hébergé de Botoi sur api.botoi.com/mcp exécute le même modèle. Parcourez le Documents de configuration MCP pour les configurations Claude Desktop, Claude Code, Cursor, VS Code et Windsurf. Pour la signature JWT et les primitives de vérification que le middleware ci-dessus utilise, voir le Points de terminaison de l'API JWT dans les documents interactifs.
FAQ
- Pourquoi PKCE pour MCP lorsque les agents ne sont pas des navigateurs ?
- PKCE (Proof Key for Code Exchange) lie le code d'autorisation à un secret cryptographique unique que seul le client initiateur connaît. Dans le contexte MCP, l’attaquant n’est pas une extension de navigateur malveillante ; il s'agit d'un agent malveillant ou d'un code d'autorisation volé flottant dans le journal d'un terminal. PKCE signifie qu'un code intercepté ne peut pas être utilisé sans le vérificateur du code d'origine. OAuth 2.1 nécessite PKCE pour chaque flux de code d'autorisation, y compris les clients confidentiels, donc MCP suit simplement les spécifications.
- Qu'est-ce qu'un document de métadonnées de ressources protégées ?
- Un document PRM est un fichier JSON servi dans /.well-known/oauth-protected-resource qui indique aux clients OAuth où réside le serveur d'autorisation, quelles étendues la ressource accepte et quel identifiant de ressource mettre dans la revendication aud. La spécification d'autorisation MCP a ajouté PRM afin qu'un client MCP découvre votre configuration d'authentification sans configuration hors bande. Le client récupère le PRM, suit l'URL des serveurs d'autorisation jusqu'aux métadonnées AS, exécute la danse OAuth et arrive sur votre serveur MCP avec un jeton de support valide.
- Ai-je besoin d’un enregistrement client dynamique ?
- Pour les serveurs MCP publics exposés à de nombreux clients, oui. L'enregistrement dynamique du client (RFC 7591) permet à un client MCP de s'auto-enregistrer sur votre serveur d'autorisation, de recevoir un client_id et de démarrer le flux OAuth en un seul aller-retour. Sans cela, chaque utilisateur doit créer manuellement une application dans votre tableau de bord avant de pouvoir connecter Claude ou Cursor. Pour les intégrations internes ou sur liste autorisée, un client_id pré-approvisionné fonctionne toujours.
- Où réside le jeton du porteur pendant la session ?
- Dans l’en-tête Authorization de chaque demande MCP. HTTP streamable rend cela propre ; chaque requête porte le jeton et votre serveur le vérifie dans le middleware avant d'envoyer l'appel à l'outil. Les jetons d'accès de courte durée (5 à 60 minutes) avec des jetons d'actualisation détenus par le client minimisent le rayon d'explosion d'une ligne de journal qui fuit. N'intégrez jamais le jeton dans l'URL ; les journaux et les proxys capturent régulièrement les URL.
- Comment les portées de l'outil MCP se comparent-elles aux portées OAuth ?
- MCP s'appuie sur une autorisation basée sur les rôles : un jeton comporte des étendues telles que tools:read, tools:invoke:safe ou tools:invoke:destructive, et les annotations d'outils individuelles déclarent les étendues dont ils ont besoin. Les étendues sont mappées un à un aux étendues OAuth, afin que vous puissiez utiliser la même conception d'étendue que vous avez déjà pour une API REST. La nouvelle pièce concerne les annotations au niveau des outils du côté MCP ; ils rendent la décision d'autorisation visible dans le registre de l'outil, pas seulement dans le code du gestionnaire.
Commencez a construire avec botoi
150+ endpoints API pour la recherche, le traitement de texte, la generation d'images et les utilitaires pour developpeurs. Offre gratuite, sans carte bancaire.