Authentifiez vos utilisateurs
De nombreux serveurs MCP de plugins peuvent fonctionner en mode anonyme et en lecture seule, mais tout accès à des données propres à un client ou à des actions d’écriture devrait nécessiter l’authentification des utilisateurs.
Les plugins publiés peuvent fonctionner dans ChatGPT et Codex. Le contrat d’autorisation MCP s’applique aux deux produits ; ce guide précise les particularités du client ChatGPT lorsqu’un callback, un document de métadonnées ou une interface de liaison diffère selon l’interface utilisée.
Vous pouvez intégrer votre propre serveur d’autorisation lorsque vous devez vous connecter à une application côté serveur existante ou partager des données entre utilisateurs.
Authentification personnalisée avec OAuth 2.1
Pour un serveur MCP avec authentification, vous devez implémenter un flux OAuth 2.1 conforme à la spécification d’autorisation MCP.
Composants
- Serveur de ressources : votre serveur MCP, qui expose des outils et vérifie les jetons d’accès à chaque requête.
- Serveur d’autorisation : votre fournisseur d’identité ou votre implémentation personnalisée, qui émet des jetons et publie des métadonnées de découverte.
- Client : l’hôte OpenAI, tel que ChatGPT ou Codex, qui agit pour le compte de l’utilisateur. Les clients pris en charge utilisent les Client ID Metadata Documents (CIMD), l’enregistrement dynamique des clients (DCR), les clients OAuth prédéfinis et PKCE.
Exigences de la spécification d’autorisation MCP
- Hébergez les métadonnées de la ressource protégée sur votre serveur MCP
- Publiez les métadonnées OAuth depuis votre serveur d’autorisation
- Retransmettez le paramètre
resourcetout au long du flux OAuth - Choisissez comment l’hôte OpenAI identifie ou enregistre son client OAuth : CIMD, DCR ou client OAuth prédéfini
- Publiez les méthodes d’authentification au point de terminaison de jetons acceptées par votre serveur d’autorisation
Voici les exigences de la spécification, expliquées simplement.
Hébergez les métadonnées de la ressource protégée sur votre serveur MCP
- Vous devez disposer d’un point de terminaison HTTPS tel que
GET https://your-mcp.example.com/.well-known/oauth-protected-resource(ou indiquer la même URL dans un en-têteWWW-Authenticatedes réponses401 Unauthorized) pour que ChatGPT sache où récupérer vos métadonnées. - Ce point de terminaison renvoie un document JSON décrivant le serveur de ressources et les serveurs d’autorisation disponibles :
{
"resource": "https://your-mcp.example.com",
"authorization_servers": ["https://auth.yourcompany.com"],
"scopes_supported": ["files:read", "files:write"],
"resource_documentation": "https://yourcompany.com/docs/mcp"
}
- Principaux champs à renseigner :
resource: l’identifiant HTTPS canonique de votre serveur MCP. ChatGPT envoie cette valeur exacte dans le paramètre de requêteresourcependant le flux OAuth.authorization_servers: une ou plusieurs URL de base d’émetteur pointant vers votre fournisseur d’identité. ChatGPT essaiera chacune d’elles pour trouver les métadonnées OAuth.scopes_supported: une liste facultative qui aide ChatGPT à expliquer les autorisations qu’il va demander à l’utilisateur.- Les champs facultatifs définis dans la RFC 9728, tels que
resource_documentation,resource_policy_uriouresource_tos_uri, aident les clients et les administrateurs à comprendre votre configuration.
Lorsque vous bloquez une requête non authentifiée, renvoyez un défi d’authentification tel que :
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://your-mcp.example.com/.well-known/oauth-protected-resource",
scope="files:read"
Ce seul en-tête permet à ChatGPT de découvrir l’URL des métadonnées, même s’il ne l’a jamais rencontrée auparavant.
Publiez les métadonnées OAuth depuis votre serveur d’autorisation
- Votre fournisseur d’identité doit exposer l’un des documents de découverte à une adresse standardisée pour que ChatGPT puisse lire sa configuration :
- Métadonnées OAuth 2.0 à l’adresse
https://auth.yourcompany.com/.well-known/oauth-authorization-server - Métadonnées OpenID Connect à l’adresse
https://auth.yourcompany.com/.well-known/openid-configuration
- Métadonnées OAuth 2.0 à l’adresse
- Chaque document répond à trois questions essentielles pour l’hôte OpenAI : où diriger l’utilisateur, comment échanger les codes et comment s’identifier. Voici un exemple de réponse type :
{
"issuer": "https://auth.yourcompany.com",
"authorization_response_iss_parameter_supported": true,
"authorization_endpoint": "https://auth.yourcompany.com/oauth2/v1/authorize",
"token_endpoint": "https://auth.yourcompany.com/oauth2/v1/token",
"client_id_metadata_document_supported": true,
"token_endpoint_auth_methods_supported": ["none", "private_key_jwt"],
"registration_endpoint": "https://auth.yourcompany.com/oauth2/v1/register",
"code_challenge_methods_supported": ["S256"],
"scopes_supported": ["files:read", "files:write"]
}
- Champs à renseigner correctement :
issuer: l’identifiant canonique du serveur d’autorisation. Utilisez cette valeur exacte dans la listeauthorization_serversdes métadonnées de la ressource protégée.authorization_response_iss_parameter_supported: définissez ce champ surtrueuniquement si votre serveur d’autorisation renvoie un paramètreissdans chaque réponse d’autorisation, y compris les réponses d’erreur.authorization_endpoint,token_endpoint: les URL dont ChatGPT a besoin pour exécuter de bout en bout le flux OAuth par code d’autorisation avec PKCE.client_id_metadata_document_supported: définissez ce champ surtruesi vous souhaitez que ChatGPT utilise CIMD pour l’enregistrement du client. ChatGPT privilégie CIMD lorsqu’il est disponible, mais le créateur du plugin peut choisir DCR lorsque les deux méthodes sont disponibles.token_endpoint_auth_methods_supported: indiquez les méthodes d’authentification au point de terminaison de jetons acceptées par votre serveur d’autorisation. Cela s’applique à CIMD, à DCR et aux clients OAuth prédéfinis. Pour CIMD, ChatGPT prend en chargenonepour l’échange de jetons par un client public etprivate_key_jwtpour l’échange de jetons avec une assertion client signée. Les autres clients OAuth utilisent généralementnone,client_secret_postouclient_secret_basic.registration_endpoint: incluez ce champ si vous prenez en charge l’enregistrement dynamique des clients (DCR), qui permet à ChatGPT de créer et de réutiliser unclient_iddédié à la connexion au serveur MCP.code_challenge_methods_supported: doit inclureS256. Les serveurs MCP ne sont pas pris en charge si les métadonnées de leur serveur d’autorisation omettent ce champ ou n’annoncent pas la prise en charge deS256, comme l’exige la spécification d’autorisation MCP.- Les champs facultatifs suivent la RFC 8414 / OpenID Discovery ; incluez ceux qui aident vos administrateurs à configurer les politiques.
Portées OIDC
- Si votre fournisseur annonce des portées OIDC (par exemple,
openid,email,profile) dans le champscopes_supportedde son document.well-known/oauth-authorization-serverou.well-known/openid-configuration, ChatGPT demande ces portées par défaut pendant le flux OAuth. - Certains fournisseurs d’identité n’activent pas nécessairement par défaut les portées OIDC qu’ils annoncent. Vérifiez les paramètres de configuration de votre fournisseur et assurez-vous que chaque portée annoncée est activée pour le client OAuth, qu’il utilise CIMD, ait été créé manuellement ou via DCR.
Prenez en charge les restrictions de domaine des espaces de travail
Les espaces de travail ChatGPT Enterprise peuvent faire vérifier qu’ils sont propriétaires de domaines de messagerie. Lorsqu’un plugin lié via OAuth fournit l’adresse e-mail vérifiée de l’utilisateur, ChatGPT peut utiliser le domaine de cette adresse pour empêcher l’utilisation de cette identité professionnelle afin de lier le plugin dans un espace de travail personnel ou un autre espace de travail extérieur à l’organisation.
Pour prendre en charge cette protection, configurez votre serveur d’autorisation comme suit :
- Publiez les métadonnées de découverte OpenID Connect.
- Annoncez et activez les portées
openidetemail. - Annoncez un point de terminaison UserInfo qui renvoie la revendication
emailde l’utilisateur etemail_verified: true.
Vous pouvez également renvoyer ces revendications dans un jeton d’identité pendant le flux OAuth, mais le point de terminaison UserInfo est requis pour les restrictions de domaine des espaces de travail.
L’espace de travail Entreprise doit également faire vérifier son domaine. Votre serveur d’autorisation fournit l’identité de l’utilisateur, que ChatGPT compare aux domaines vérifiés configurés pour l’espace de travail ; il ne vérifie pas que l’espace de travail est propriétaire d’un domaine.
Préservez le contexte de connexion lors d’une nouvelle autorisation
Lorsque ChatGPT renouvelle l’autorisation d’une liaison existante, notamment pour demander des portées OAuth supplémentaires, il peut inclure le jeton d’identité OIDC précédent dans la requête d’autorisation via le paramètre standard id_token_hint. Pour permettre aux utilisateurs d’accorder des portées supplémentaires sans reprendre la connexion depuis le début, configurez votre serveur d’autorisation pour qu’il émette un jeton d’identité lors du flux OAuth initial et qu’il tienne compte de id_token_hint lors de l’autorisation.
Cette optimisation est facultative. Le renouvellement de l’autorisation fonctionne même si aucun jeton d’identité n’est disponible ou si votre serveur d’autorisation n’utilise pas cette indication.
Protégez les callbacks grâce à l’identification de l’émetteur
Les hôtes OpenAI utilisent l’identification de l’émetteur définie dans la RFC 9207 pour protéger les callbacks OAuth contre les attaques par confusion de serveurs d’autorisation. Pour permettre à ChatGPT et Codex d’utiliser un URI de redirection stable lors de la création d’un client OAuth éligible :
- Définissez
authorization_response_iss_parameter_supported: truedans les métadonnées de votre serveur d’autorisation. - Utilisez exactement le même identifiant d’émetteur dans le champ
issuerdes métadonnées et dans la listeauthorization_serversdes métadonnées de la ressource protégée. - Renvoyez
issdans chaque réponse d’autorisation, qu’elle indique un succès ou une erreur. Sa valeur doit correspondre exactement au champissuerdes métadonnées ; les clients comparent les chaînes à l’identique, sans normaliser les barres obliques finales, les chemins, les ports ou la casse.
ChatGPT et Codex enregistrent la valeur issuer des métadonnées sélectionnées avant de rediriger
l’utilisateur et vérifient la valeur iss renvoyée avant d’échanger le code
d’autorisation. Si le serveur annonce la prise en charge de l’identification de l’émetteur, mais omet iss ou
renvoie une valeur qui ne correspond pas, ChatGPT et Codex rejettent la réponse. Ces exigences
suivent les règles de validation des réponses
d’autorisation MCP.
URL de redirection
Copiez l’URI de redirection de production exacte affichée sur la page de gestion du serveur MCP dans la liste d’autorisation de votre serveur d’autorisation.
- Si votre serveur d’autorisation ne respecte pas les exigences d’identification de l’émetteur
ci-dessus, ChatGPT utilise l’URI de redirection propre à l’identifiant de rappel
https://chatgpt.com/connector/oauth/{callback_id}. - Si votre serveur d’autorisation respecte ces exigences, ChatGPT utilise
l’URI de redirection stable
https://chatgpt.com/connector_platform_oauth_redirect.
Les serveurs MCP publiés avant l’introduction des redirections propres à l’identifiant de rappel dans ChatGPT continuent également d’utiliser l’URI de redirection stable.
Répercutez le paramètre resource tout au long du flux OAuth
- Prévoyez que ChatGPT ajoute
resource=https%3A%2F%2Fyour-mcp.example.comaux requêtes d’autorisation comme aux requêtes de token. Cela relie le token aux métadonnées de la ressource protégée présentées ci-dessus. - Configurez votre serveur d’autorisation pour qu’il copie cette valeur dans le token d’accès (généralement dans la revendication
aud), afin que votre serveur MCP puisse vérifier que le token a été émis exclusivement pour lui. - Si un token arrive sans l’audience ou les portées attendues, rejetez-le et utilisez le défi d’authentification
WWW-Authenticatepour inviter ChatGPT à relancer l’autorisation avec les bons paramètres.
Prenez en charge le flux par code d’autorisation
- ChatGPT, qui agit en tant que client MCP, exécute le flux par code d’autorisation avec PKCE en utilisant la méthode de défi de code
S256, afin qu’un attaquant ne puisse pas réutiliser les codes d’autorisation interceptés. - Votre serveur d’autorisation doit publier
code_challenge_methods_supportedavecS256pour que les clients puissent confirmer la prise en charge de PKCE à partir des métadonnées.
Flux OAuth
Si vous avez implémenté la spécification d’autorisation MCP décrite ci-dessus, le flux OAuth se déroule comme suit :
- ChatGPT interroge votre serveur MCP pour obtenir les métadonnées de la ressource protégée.

- ChatGPT s’identifie comme client OAuth. Lorsque le serveur MCP utilise CIMD, ChatGPT ignore l’enregistrement dynamique du client et envoie l’URL d’un document CIMD comme
client_id. Pour les serveurs d’autorisation qui respectent les exigences d’identification de l’émetteur ci-dessus, ChatGPT utilise l’URL stablehttps://chatgpt.com/oauth/client.json; pour les autres serveurs, il utilise l’URL propre à l’identifiant de rappelhttps://chatgpt.com/oauth/{callback_id}/client.json. La page de gestion du serveur MCP affiche le document de métadonnées du client et l’URI de redirection exacts correspondant au mode de rappel de la connexion. Lorsque le serveur MCP utilise DCR, ChatGPT appelle une seule fois leregistration_endpointde votre serveur d’autorisation pour la connexion au serveur MCP, reçoit unclient_idgénéré et réutilise ce client pour cette connexion.
Avec CIMD, il n’y a pas d’étape d’enregistrement du client. L’écran suivant illustre le parcours DCR :

- Lorsque l’utilisateur appelle un outil pour la première fois, le client ChatGPT lance le flux OAuth par code d’autorisation avec PKCE. L’utilisateur s’authentifie et consent aux portées demandées.

- ChatGPT échange le code d’autorisation contre un token d’accès et le joint aux requêtes MCP suivantes (
Authorization: Bearer <token>).

- Votre serveur vérifie le token à chaque requête (émetteur, audience, expiration, portées) avant d’exécuter l’outil.
Enregistrement du client
Privilégiez les documents de métadonnées d’identifiant client (CIMD) comme méthode d’enregistrement du client lorsque votre serveur d’autorisation les prend en charge et que le développeur du plugin choisit cette méthode. Avec CIMD, ChatGPT utilise l’URL HTTPS d’un document de métadonnées comme client_id. Votre serveur d’autorisation récupère ce document, valide les métadonnées du client publiées ainsi que les identifiants de ressource de redirection, et traite l’URL comme l’identité client stable de ChatGPT.
Si vous prenez en charge CIMD, définissez client_id_metadata_document_supported: true dans les métadonnées de votre serveur d’autorisation. ChatGPT peut ainsi utiliser une identité client stable unique pour les serveurs MCP qui choisissent CIMD. Votre serveur d’autorisation peut s’appuyer sur cette identité pour les listes d’URI de redirection autorisées, les limites de débit et d’autres politiques.
ChatGPT adopte la transition CIMD proposée dans
MCP SEP-3149.
Son document CIMD de production publie
token_endpoint_auth_methods_supported sous la forme d’un tableau des méthodes que ChatGPT
peut utiliser, sans ordre de préférence. Pendant la transition, il publie également
l’ancien champ au singulier token_endpoint_auth_method pour indiquer une préférence :
{
"token_endpoint_auth_methods_supported": ["none", "private_key_jwt"],
"token_endpoint_auth_method": "private_key_jwt"
}
Le champ au pluriel ne décrit pas le même côté de l’échange dans les deux documents : les métadonnées du serveur d’autorisation répertorient les méthodes acceptées par votre point de terminaison de token, tandis que le document CIMD de ChatGPT répertorie les méthodes que ChatGPT peut utiliser. ChatGPT sélectionne une méthode commune aux deux ensembles. Lorsque la méthode préférée indiquée dans l’ancien champ au singulier appartient aux deux ensembles, ChatGPT l’utilise pour rester compatible avec les serveurs d’autorisation qui considèrent encore ce champ comme contraignant. Sinon, ChatGPT peut utiliser une autre méthode commune aux deux ensembles.
Les serveurs d’autorisation qui lisent le champ CIMD au pluriel devraient accepter toute méthode
commune aux deux ensembles, sauf si la politique de sécurité locale l’interdit pour le
client. Ils doivent rejeter les méthodes qui ne sont pas communes aux deux ensembles. L’URL client_id
reste stable et n’utilise pas de paramètres de requête pour sélectionner un document
propre à une méthode.
Les méthodes prises en charge sont les suivantes :
none: utilisez ce flux pour client public lorsque votre point de terminaison de token prend en charge l’échange du code d’autorisation avec PKCE sans authentification du client. ChatGPT ne stocke pas de secret propre à chaque client.private_key_jwt: utilisez ce flux avec assertion client signée lorsque votre point de terminaison de token exige l’authentification du client. ChatGPT publie une URL JWKS publique dans ses métadonnées CIMD. Le JWKS est servi depuis/oauth/jwks.jsonsur l’origine des métadonnées. ChatGPT signe les requêtes de token côté serveur avec une clé privée gérée et unkid; votre serveur d’autorisation vérifie l’assertion à l’aide du JWKS public.
DCR reste pris en charge. Si vous incluez registration_endpoint, ChatGPT peut s’enregistrer dynamiquement lorsque le développeur du plugin choisit DCR ou que CIMD n’est pas disponible. ChatGPT exécute DCR une seule fois par connexion au serveur MCP, puis conserve et réutilise le client OAuth enregistré pour cette connexion. DCR peut toutefois créer de nombreux clients enregistrés pour de nombreuses connexions distinctes ; CIMD est donc généralement plus facile à administrer à grande échelle.
Veillez à ce que le client OAuth enregistré et tout secret client restent valides tant que la connexion au serveur MCP est utilisée. Si votre serveur d’autorisation fait expirer, supprime ou remplace l’un de ces identifiants, les utilisateurs et les personnes chargées de la révision peuvent recevoir une erreur invalid_client lorsqu’ils se connectent. Les tokens d’accès et de rafraîchissement peuvent toujours expirer ou faire l’objet d’une rotation normalement.
Identification du client
Une question fréquente est de savoir comment votre serveur MCP peut confirmer qu’une requête provient bien de ChatGPT. ChatGPT présente un certificat client géré par OpenAI lorsqu’il se connecte aux serveurs MCP, ce qui vous permet de vérifier le client au niveau de la couche de transport avec mTLS. Vous pouvez également ajouter les plages d’adresses IP de sortie publiées de ChatGPT à votre liste d’autorisation. ChatGPT ne prend pas en charge les mécanismes d’octroi OAuth de machine à machine, tels que les identifiants client, les comptes de service ou les assertions JWT bearer, et ne peut pas non plus présenter de clés API personnalisées ni de certificats mTLS fournis par le client.
CIMD renforce encore l’identification du client en fournissant à votre serveur d’autorisation une déclaration stable de l’identité de ChatGPT, hébergée en HTTPS. Lorsque vous utilisez private_key_jwt, vérifiez l’assertion client que ChatGPT envoie au point de terminaison de token à l’aide du JWKS public publié dans les métadonnées CIMD.
TLS mutuel (mTLS)
ChatGPT présente désormais un certificat client géré par OpenAI lors de l’établissement de connexions TLS aux serveurs MCP. Si votre application valide les certificats clients, configurez-la pour qu’elle fasse confiance à la chaîne de certificats OpenAI ci-dessous.
-
Téléchargez le certificat de l’autorité de certification racine OpenAI
-
Téléchargez le certificat de l’autorité de certification intermédiaire OpenAI Connectors mTLS
Pour valider le certificat client lors de l’établissement de la connexion TLS à votre serveur MCP :
- Vérifiez qu’un certificat terminal est présent et que sa chaîne remonte à l’autorité de certification intermédiaire OpenAI Connectors mTLS.
- Vérifiez que le certificat terminal est valide pour l’authentification du client.
- Vérifiez que l’entrée SAN
dnsNamedu certificat terminal a pour valeurmtls.prod.connectors.openai.com. - Évitez d’épingler l’empreinte d’un certificat terminal ; OpenAI peut remplacer ce certificat tout en le conservant sous la chaîne d’autorités de certification publiée.
Utilisez mTLS pour authentifier ChatGPT en tant que client MCP. Continuez d’utiliser OAuth 2.1 pour authentifier l’utilisateur final et autoriser l’accès aux outils.
Choix d’un fournisseur d’identité
La plupart des fournisseurs d’identité OAuth 2.1 peuvent satisfaire aux exigences d’autorisation MCP dès lors qu’ils exposent un document de découverte, prennent en charge CIMD avec none ou private_key_jwt, prennent en charge DCR si nécessaire et répercutent le paramètre resource dans les tokens émis. Privilégiez les fournisseurs qui prennent en charge CIMD pour l’enregistrement des clients.
Nous vous recommandons vivement d’utiliser un fournisseur d’identité existant et reconnu plutôt que de développer vous-même l’authentification à partir de zéro.
Voici les instructions pour quelques fournisseurs d’identité courants.
Auth0
Auth0 permet aux clients MCP de se connecter en toute sécurité aux serveurs MCP en assurant la découverte des métadonnées, l’enregistrement CIMD, la sécurité des API et l’échange de tokens pour les appels à vos propres outils et à ceux de tiers.
- Guide de configuration d’Auth0 pour l’autorisation MCP
- Vue d’ensemble de la sécurisation des serveurs MCP avec Auth0
- Guides de démarrage rapide pour sécuriser les serveurs MCP avec Auth0
Exemple de fournisseur hébergé
- Guide du fournisseur sur l’autorisation MCP
- Vue d’ensemble de l’autorisation MCP
- Guide d’authentification pour l’interface de ChatGPT
Implémentation de la vérification des tokens
Une fois le flux OAuth terminé, ChatGPT joint directement le token d’accès reçu aux requêtes MCP suivantes (Authorization: Bearer …). Lorsqu’une requête atteint votre serveur MCP, vous devez considérer le token comme non fiable et effectuer vous-même l’ensemble des contrôles du serveur de ressources : validation de la signature, correspondance de l’émetteur et de l’audience, expiration, prise en compte des risques de rejeu et application des portées. Cette responsabilité vous incombe, et non à ChatGPT.
En pratique, suivez ces recommandations :
- Récupérez les clés de signature publiées par votre serveur d’autorisation (généralement via JWKS) et vérifiez la signature du token ainsi que sa revendication
iss. - Rejetez les tokens qui ont expiré ou qui ne sont pas encore valides (
exp/nbf). - Vérifiez que le token a été émis pour votre serveur (
audou la revendicationresource) et qu’il contient les portées que vous avez définies comme obligatoires. - Effectuez les contrôles de politique propres au serveur, puis joignez l’identité déterminée au contexte de la requête ou renvoyez un code
401accompagné d’un défi d’authentificationWWW-Authenticate.
Si la vérification échoue, répondez avec 401 Unauthorized et un en-tête WWW-Authenticate qui pointe vers les métadonnées de votre ressource protégée. Cela indique au client qu’il doit relancer le flux OAuth.
Primitives de vérification des tokens dans les SDK
Les SDK MCP pour Python et TypeScript incluent des fonctions utilitaires pour vous éviter de tout implémenter vous-même.
Prenez en charge plusieurs comptes
La prise en charge de plusieurs comptes permet aux utilisateurs de connecter plusieurs comptes au même plugin, par exemple un compte personnel et un compte professionnel. OpenAI achemine chaque appel d’outil en utilisant les informations d’authentification de la connexion sélectionnée. Les utilisateurs peuvent connecter plusieurs comptes sans outil de profil. Pour les aider à distinguer les connexions et à reconnaître un même profil après une reconnexion, fournissez un outil de profil nécessitant une authentification, avec un identifiant stable et des métadonnées d’affichage utiles.
Fonctionnement de la prise en charge de plusieurs comptes pour les utilisateurs
Les utilisateurs peuvent connecter des comptes supplémentaires depuis la page des paramètres du plugin. Tous les comptes connectés sont accessibles au modèle, qui sélectionne le ou les comptes pertinents lors des appels d’outils en fonction de la demande de l’utilisateur. Chaque appel d’outil utilise les informations d’authentification et les autorisations du compte sélectionné.
Améliorez l’identification des comptes
Pour aider OpenAI à reconnaître les profils connectés et à afficher des libellés utiles :
- Fournissez un outil de profil nécessitant une authentification qui renvoie un identifiant opaque identifiant de manière unique et stable le profil représenté par les informations d’authentification de la requête. Cela permet à OpenAI de reconnaître un même profil d’une reconnexion à l’autre et de le distinguer des autres profils. Un champ nommé
idn’est utile à cette fin que si sa valeur respecte ces garanties. - Désignez l’outil de profil dans les métadonnées MCP pour qu’OpenAI puisse découvrir quel outil appeler afin d’obtenir les informations du profil authentifié.
Lorsque des informations de profil sont nécessaires, OpenAI découvre l’outil désigné à l’exécution, l’appelle avec les informations d’authentification de la connexion et valide la réponse avant d’utiliser les données du profil. Sans outil de profil, les utilisateurs peuvent toujours connecter des comptes, mais les libellés des comptes, leur reconnaissance ou la détection des doublons peuvent être moins fiables. Si vous déclarez un outil de profil, renvoyez une identité valide ; une réponse non valide peut empêcher la connexion du compte.
Définissez une identité de profil stable
Un profil correspond à l’identité représentée par les informations d’authentification de la requête authentifiée. Votre service définit les profils qui peuvent être connectés indépendamment ; ce contrat n’impose ni l’organisation de votre service ni son modèle d’autorisation.
Renvoyez un identifiant de profil opaque et unique au sein de votre application. Un même profil doit conserver son identifiant lors du renouvellement des tokens et des reconnexions ; des profils distincts doivent avoir des identifiants distincts. OpenAI compare ces identifiants sans interpréter leur contenu.
Utilisez un identifiant de fournisseur existant, immuable et opaque s’il identifie le profil dans son intégralité. Sinon, attribuez une seule fois un identifiant opaque, enregistrez durablement son association avec ce profil et récupérez le même identifiant lors des requêtes ultérieures. Conservez les relations internes au sein de votre service ; n’encodez ni noms, ni adresses e-mail, ni relations organisationnelles dans l’identifiant renvoyé.
Votre id doit :
- Être une chaîne non vide qui ne se compose pas uniquement de caractères d’espacement. Sérialisez les identifiants numériques des fournisseurs sous forme de chaînes.
- Rester identique pour un même profil lors du renouvellement des tokens, des reconnexions et de l’élargissement des portées d’accès.
- Être différent pour chaque profil distinct pouvant se connecter via l’application.
- Rester inchangé lorsque l’adresse e-mail, le nom ou le libellé affiché du profil change.
- Ne jamais être réattribué à un autre profil après la suppression du profil.
Ne générez pas de nouvel identifiant à chaque connexion, token, session ou appel d’outil. Conservez l’adresse e-mail et les noms modifiables dans les métadonnées d’affichage : une adresse e-mail susceptible de changer ou d’être réattribuée ne peut pas servir d’identifiant de profil stable. Pour Google OIDC, utilisez la valeur stable sub plutôt que le claim d’adresse e-mail ; la documentation de Google précise que l’adresse e-mail peut changer, tandis que sub reste inchangé et n’est jamais réutilisé. Consultez la documentation de Google sur l’identité.
Conservez les identifiants de profil existants lorsque vous mettez à jour votre intégration. Un changement de nom d’affichage, un nouveau token ou une nouvelle connexion ne doit pas créer de nouvelle identité de profil.
Implémentez et déclarez votre outil de profil
Exposez un outil en lecture seule nécessitant une authentification, qui accepte un objet d’arguments vide et renvoie le profil actuel. L’outil peut s’appeler get_profile, whoami ou porter un autre nom ; ses métadonnées l’identifient comme l’outil de profil à découvrir à l’exécution. La réponse doit satisfaire aux exigences d’identité ci-dessous pour qu’OpenAI puisse l’utiliser correctement.
- Déterminez l’identité à partir des informations d’authentification validées de la requête.
- Rendez l’opération accessible en lecture seule avec les autorisations habituelles de la connexion.
- Renvoyez exactement un profil : celui que représentent les informations d’authentification de la requête actuelle.
- N’exigez pas que l’appelant fournisse un identifiant utilisateur, une adresse e-mail ou un sélecteur de compte.
- En cas d’échec de l’authentification, renvoyez l’erreur d’authentification appropriée plutôt qu’un identifiant factice ou le profil d’un autre compte.
La réponse de profil doit être conforme au schéma JSON Schema suivant :
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1,
"pattern": "\\S",
"description": "Opaque profile identifier, unique within this app and unchanged across token refresh, reconnection, and display-metadata changes. Never reassigned to another profile."
},
"name": {
"type": "string",
"description": "Display name for the authenticated profile."
},
"email": {
"type": "string",
"description": "Email address for display; not used as the profile identity."
},
"nickname": {
"type": "string",
"description": "A useful label that helps users distinguish connected profiles."
}
},
"required": ["id"],
"additionalProperties": false
}
La réponse doit contenir un champ id dont la valeur est une chaîne non vide qui ne se compose pas uniquement de caractères d’espacement. Les champs d’affichage sont facultatifs. Les métadonnées de l’outil indiquent à OpenAI où récupérer les informations de profil ; la réponse identifie le profil représenté par les informations d’authentification actuelles.
La validation du schéma vérifie si la réponse possède la structure et les types de champs nécessaires à la gestion des profils. Votre service doit également garantir l’unicité et la stabilité des identifiants, ainsi que la correspondance entre le profil et les informations d’authentification ; ni les métadonnées ni la réussite de la validation du schéma ne prouvent que ces propriétés sont respectées en pratique.
Incluez name, email et/ou nickname lorsqu’ils sont disponibles afin que les utilisateurs puissent distinguer les profils. Omettez les valeurs facultatives indisponibles ; ne les inventez pas et n’ajoutez pas de données personnelles sans rapport. Placez les éléments de contexte utiles et lisibles par un humain dans nickname plutôt que dans l’identifiant.
Marquez l’outil avec _meta["openai/profile"]: true et publiez le schéma de réponse du profil dans son champ outputSchema. Le marqueur indique à OpenAI quel outil fournit les informations de profil ; il n’active pas la fonctionnalité et ne rend pas l’application éligible. Un marqueur absent ou défini sur false signifie que cet outil n’est pas désigné comme source de profil par ce mécanisme. Les chaînes, les nombres et null ne sont pas des valeurs valides pour ce marqueur.
{
"name": "get_profile",
"description": "Return the profile represented by this request's authenticated credentials. The opaque id is unique within this app and remains unchanged across token refresh, reconnection, and display-metadata changes.",
"inputSchema": {
"type": "object",
"properties": {},
"additionalProperties": false
},
"outputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1,
"pattern": "\\S",
"description": "Opaque profile identifier, unique within this app and unchanged across token refresh, reconnection, and display-metadata changes. Never reassigned to another profile."
},
"name": {
"type": "string",
"description": "Display name for the authenticated profile."
},
"email": {
"type": "string",
"description": "Email address for display; not used as the profile identity."
},
"nickname": {
"type": "string",
"description": "A useful label that helps users distinguish connected profiles."
}
},
"required": ["id"],
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"destructiveHint": false,
"openWorldHint": false
},
"securitySchemes": [
{
"type": "oauth2",
"scopes": []
}
],
"_meta": {
"openai/profile": true
}
}
Utilisez les portées OAuth réelles de votre intégration si l’accès au profil les exige. La déclaration n’implémente pas l’authentification ; le serveur doit valider les informations d’authentification et faire respecter les autorisations. Consultez la section Implémentez la vérification des tokens et la référence des outils.
Renvoyez le profil dans structuredContent afin qu’il puisse être validé par rapport à outputSchema. Pour assurer la compatibilité, incluez également le même profil sérialisé en JSON dans un élément de contenu textuel :
{
"content": [
{
"type": "text",
"text": "{\"id\":\"prf_8d7e4b19\",\"name\":\"Alex Chen\",\"email\":\"alex@example.com\",\"nickname\":\"Alex — Moonwaffle work\"}"
}
],
"structuredContent": {
"id": "prf_8d7e4b19",
"name": "Alex Chen",
"email": "alex@example.com",
"nickname": "Alex — Moonwaffle work"
},
"isError": false
}
Utilisez un seul objet JSON dont les champs de profil se trouvent au premier niveau.
Vous avez déjà un outil de profil ? Conservez son nom, ajoutez la déclaration des métadonnées de profil et renvoyez la réponse de profil standard. Si la réponse existante a une structure différente, adaptez-la sur votre serveur ou exposez un petit outil d’adaptation conforme au schéma. La méthode d’intégration standard utilise la même déclaration et la même structure de réponse pour toutes les applications.
Exemple concret : profils Moonwaffle persistants
Supposons que Moonwaffle, un service fictif, permette à Alex de connecter deux profils indépendamment. Moonwaffle stocke un identifiant opaque différent pour chaque profil. Les informations d’authentification de la requête permettent de retrouver l’un de ces profils stockés, et l’outil de profil renvoie son identifiant existant.
Exemple de profils stockés. Les libellés peuvent changer ; les identifiants restent les mêmes :
Alex — Moonwaffle personal: prf_42a9c6e0
Alex — Moonwaffle work: prf_8d7e4b19
Ces exemples d’identifiants n’encodent ni les libellés des profils ni les relations internes. Ils sont enregistrés durablement une seule fois par profil et réutilisés lors des reconnexions, du renouvellement des tokens et des changements d’adresse e-mail ou de nom d’affichage.
Construisez la réponse à partir du profil authentifié. Cet exemple JavaScript présente la logique d’un gestionnaire que vous pouvez raccorder à votre SDK MCP. loadAuthenticatedProfile correspond au code d’intégration de votre application : il valide les informations d’authentification de la requête, fait respecter les autorisations associées et récupère l’identifiant persistant ainsi que les métadonnées d’affichage du profil correspondant. requestContext provient du traitement des requêtes par votre serveur ; ce n’est pas un argument d’outil fourni par le modèle.
async function getProfile(requestContext) {
// Your auth/provider integration validates credentials and loads
// the existing profile. Auth failures use normal MCP auth handling.
const account = await loadAuthenticatedProfile(requestContext);
const id = account.profileId;
if (typeof id !== "string" || id.trim().length === 0) {
return {
isError: true,
content: [{ type: "text", text: "Profile identity unavailable." }],
};
}
// Return the persisted ID unchanged; do not generate an ID per call.
const profile = {
id,
...(typeof account.name === "string" ? { name: account.name } : {}),
...(typeof account.email === "string" ? { email: account.email } : {}),
...(typeof account.nickname === "string"
? { nickname: account.nickname }
: {}),
};
return {
isError: false,
structuredContent: profile,
content: [{ type: "text", text: JSON.stringify(profile) }],
};
}
Enregistrez ce gestionnaire avec la déclaration des métadonnées et les schémas d’entrée et de sortie ci-dessus. loadAuthenticatedProfile doit retrouver le même profil stocké pour des informations d’authentification équivalentes et après une reconnexion. Il ne doit pas créer de nouvel identifiant de profil pour chaque autorisation OAuth accordée ou chaque session. Tous les autres outils doivent utiliser les informations d’authentification de la requête pour faire respecter les autorisations de ce même profil.
Vérifiez le comportement de l’identité :
| Test | Résultat attendu |
|---|---|
| Appels répétés pour le profil professionnel Moonwaffle | prf_8d7e4b19 à chaque fois |
| Le même profil après le renouvellement d’un token, une reconnexion ou un élargissement des portées d’accès | prf_8d7e4b19 |
| Le même profil après un changement d’adresse e-mail ou de libellé affiché | prf_8d7e4b19 ; les libellés peuvent changer |
| Profil personnel Moonwaffle | prf_42a9c6e0, distinct de celui du profil professionnel |
| L’identifiant de profil enregistré est absent ou vide | Un résultat d’erreur ; aucune identité inventée ni aucun recours à un autre profil |
La garantie d’identité doit être respectée pour tous les profils et lors des futures modifications de votre intégration. Préservez-la indépendamment des métadonnées d’affichage, du contenu des tokens et des événements du cycle de vie des connexions.
Tests et déploiement
- Tests locaux : Commencez avec un tenant de développement qui émet des tokens à courte durée de validité pour pouvoir itérer rapidement.
- Tests internes : Une fois l’authentification opérationnelle, limitez l’accès à des testeurs de confiance avant de généraliser le déploiement. Vous pouvez exiger l’association d’un compte pour certains outils ou pour l’ensemble du serveur MCP.
- Rotation : Prévoyez la révocation et le renouvellement des tokens, ainsi que les changements de portées. Votre serveur doit considérer les requêtes dont le token est absent ou périmé comme non authentifiées et renvoyer un message d’erreur utile.
- Débogage OAuth : Utilisez les paramètres Auth de MCP Inspector pour parcourir chaque étape OAuth et repérer précisément où le flux échoue avant la mise en production.
Une fois l’authentification en place, vous pouvez proposer aux utilisateurs de ChatGPT et de Codex des données qui leur sont propres et des actions d’écriture.
Déclenchement de l’interface d’authentification
ChatGPT n’affiche son interface d’association de compte OAuth que lorsque votre serveur MCP indique qu’OAuth est disponible ou nécessaire.
Le déclenchement du flux OAuth au niveau d’un outil nécessite à la fois des métadonnées (securitySchemes et le document de métadonnées de la ressource) et des erreurs d’exécution contenant _meta["mcp/www_authenticate"]. Sans ces deux éléments, ChatGPT n’affiche pas l’interface d’association de compte pour cet outil.
-
Publiez les métadonnées de la ressource. Le serveur MCP doit exposer sa configuration OAuth à une URL standardisée, telle que
https://your-mcp.example.com/.well-known/oauth-protected-resource. -
Décrivez la politique d’authentification de chaque outil avec
securitySchemes. DéclarersecuritySchemespour chaque outil indique à ChatGPT lesquels nécessitent OAuth et lesquels peuvent être exécutés de manière anonyme. Conservez ces déclarations par outil, même si l’ensemble du serveur utilise la même politique ; les valeurs par défaut définies au niveau du serveur compliquent l’évolution ultérieure des outils pris individuellement.Deux types de schémas sont actuellement disponibles. Vous pouvez en déclarer plusieurs pour indiquer que l’authentification est facultative :
noauth: l’outil peut être appelé de manière anonyme ; ChatGPT peut l’exécuter immédiatement.oauth2: l’outil nécessite un token d’accès OAuth 2.0 ; incluez les portées que vous demanderez afin que l’écran de consentement les présente correctement.
Si vous omettez complètement le tableau, l’outil hérite de la politique par défaut annoncée par le serveur. Déclarer à la fois
noauthetoauth2indique à ChatGPT qu’il peut commencer par des appels anonymes, mais que l’association d’un compte donne accès à des fonctionnalités nécessitant des privilèges. Quelles que soient les informations transmises au client, votre serveur doit toujours vérifier le token, les portées et l’audience à chaque appel.Exemple (accès public + authentification facultative) — SDK TypeScript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; declare const server: McpServer; server.registerTool( "search", { title: "Public Search", description: "Search public documents.", inputSchema: { q: z.string(), }, outputSchema: {}, securitySchemes: [ { type: "noauth" }, { type: "oauth2", scopes: ["search.read"] }, ], }, async ({ q }) => { return { content: [{ type: "text", text: `Results for ${q}` }], structuredContent: {}, }; } );Exemple (authentification obligatoire) — SDK TypeScript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; declare const server: McpServer; server.registerTool( "create_doc", { title: "Create Document", description: "Make a new doc in your account.", inputSchema: { title: z.string(), }, outputSchema: {}, securitySchemes: [{ type: "oauth2", scopes: ["docs.write"] }], }, async ({ title }) => { return { content: [{ type: "text", text: `Created doc: ${title}` }], structuredContent: {}, }; } ); -
Vérifiez les tokens dans le gestionnaire de l’outil et renvoyez
_meta["mcp/www_authenticate"]lorsque vous souhaitez que ChatGPT affiche l’interface d’authentification. Inspectez le token et vérifiez l’émetteur, l’audience, l’expiration et les portées. En l’absence de token valide, renvoyez un résultat d’erreur contenant_meta["mcp/www_authenticate"]et assurez-vous que sa valeur contient à la fois un paramètreerroret un paramètreerror_description. C’est ce contenuWWW-Authenticatequi déclenche effectivement l’interface OAuth au niveau de l’outil une fois les étapes 1 et 2 en place. Lorsqu’un défi d’authentification demande une nouvelle autorisation, votre fournisseur peut préserver le contexte de connexion existant de l’utilisateur au cours de ce flux.Exemple
{ "jsonrpc": "2.0", "id": 4, "result": { "content": [ { "type": "text", "text": "Authentication required: no access token provided." } ], "_meta": { "mcp/www_authenticate": [ "'Bearer resource_metadata=\"https://your-mcp.example.com/.well-known/oauth-protected-resource\", error=\"insufficient_scope\", error_description=\"You need to login to continue\"'" ] }, "isError": true } }