Tutoriel : Qui suis-je ? (Tutorial: Who am I?)
Ce tutoriel vous guidera à travers le processus de configuration de MCP Auth pour authentifier les utilisateurs et récupérer leurs informations d'identité depuis le serveur d’autorisation (Authorization Server).
Après avoir terminé ce tutoriel, vous aurez :
- ✅ Une compréhension de base de l’utilisation de MCP Auth pour authentifier les utilisateurs.
- ✅ Un serveur MCP qui offre un outil pour récupérer les informations d'identité utilisateur.
Vue d’ensemble
Le tutoriel impliquera les composants suivants :
- Serveur MCP : Un serveur MCP simple qui utilise les SDK officiels MCP pour gérer les requêtes.
- Inspecteur MCP : Un outil de test visuel pour les serveurs MCP. Il agit également comme un client OAuth / OIDC pour initier le flux d’autorisation et récupérer les jetons d’accès (Access tokens).
- Serveur d’autorisation (Authorization server) : Un fournisseur OAuth 2.1 ou OpenID Connect qui gère les identités utilisateur et émet les jetons d’accès (Access tokens).
Voici un schéma de haut niveau de l’interaction entre ces composants :
Comprendre votre serveur d’autorisation
Récupérer les informations d'identité utilisateur
Pour compléter ce tutoriel, votre serveur d’autorisation doit offrir une API pour récupérer les informations d'identité utilisateur :
- Logto
- Keycloak
- OIDC
- OAuth 2
Logto est un fournisseur OpenID Connect qui prend en charge l’endpoint userinfo standard pour récupérer les informations d'identité utilisateur.
Pour obtenir un jeton d’accès (Access token) utilisable sur l’endpoint userinfo, au moins deux portées (Scopes) sont requises : openid
et profile
. Vous pouvez continuer à lire, car nous aborderons la configuration des portées plus loin.
Keycloak est une solution open-source de gestion des identités et des accès qui prend en charge plusieurs protocoles, dont OpenID Connect (OIDC). En tant que fournisseur OIDC, il implémente l’endpoint userinfo standard pour récupérer les informations d'identité utilisateur.
Pour obtenir un jeton d’accès (Access token) utilisable sur l’endpoint userinfo, au moins deux portées (Scopes) sont requises : openid
et profile
. Vous pouvez continuer à lire, car nous aborderons la configuration des portées plus loin.
La plupart des fournisseurs OpenID Connect prennent en charge l’endpoint userinfo pour récupérer les informations d'identité utilisateur.
Consultez la documentation de votre fournisseur pour vérifier s’il prend en charge cet endpoint. Si votre fournisseur prend en charge OpenID Connect Discovery, vous pouvez également vérifier si le userinfo_endpoint
est inclus dans le document de découverte (réponse de l’endpoint .well-known/openid-configuration
).
Pour obtenir un jeton d’accès (Access token) utilisable sur l’endpoint userinfo, au moins deux portées (Scopes) sont requises : openid
et profile
. Consultez la documentation de votre fournisseur pour voir la correspondance des portées avec les revendications d'identité utilisateur.
Bien que OAuth 2.0 ne définisse pas de méthode standard pour récupérer les informations d'identité utilisateur, de nombreux fournisseurs implémentent leurs propres endpoints à cet effet. Consultez la documentation de votre fournisseur pour savoir comment récupérer les informations d'identité utilisateur à l’aide d’un jeton d’accès (Access token) et quels paramètres sont requis pour obtenir ce jeton lors de l’appel du flux d’autorisation.
Enregistrement dynamique du client
L’enregistrement dynamique du client n’est pas requis pour ce tutoriel, mais il peut être utile si vous souhaitez automatiser le processus d’enregistrement du client MCP auprès de votre serveur d’autorisation. Consultez L’enregistrement dynamique du client est-il requis ? pour plus de détails.
Configurer le serveur MCP
Nous allons utiliser les SDK officiels MCP pour créer un serveur MCP avec un outil whoami
qui récupère les informations d'identité utilisateur depuis le serveur d’autorisation.
Créer un nouveau projet
- Python
- Node.js
mkdir mcp-server
cd mcp-server
uv init # Ou utilisez `pipenv` ou `poetry` pour créer un nouvel environnement virtuel
Créez un nouveau projet Node.js :
mkdir mcp-server
cd mcp-server
npm init -y # Ou utilisez `pnpm init`
npm pkg set type="module"
npm pkg set main="whoami.js"
npm pkg set scripts.start="node whoami.js"
Installer le SDK MCP et les dépendances
- Python
- Node.js
pip install "mcp[cli]" starlette uvicorn
Ou tout autre gestionnaire de paquets que vous préférez, comme uv
ou poetry
.
npm install @modelcontextprotocol/sdk express
Ou tout autre gestionnaire de paquets que vous préférez, comme pnpm
ou yarn
.
Créer le serveur MCP
Commençons par créer un serveur MCP qui implémente un outil whoami
.
- Python
- Node.js
Créez un fichier nommé whoami.py
et ajoutez le code suivant :
from mcp.server.fastmcp import FastMCP
from starlette.applications import Starlette
from starlette.routing import Mount
from typing import Any
mcp = FastMCP("WhoAmI")
@mcp.tool()
def whoami() -> dict[str, Any]:
"""Un outil qui retourne les informations de l’utilisateur courant."""
return {"error": "Not authenticated"}
app = Starlette(
routes=[Mount('/', app=mcp.sse_app())]
)
Lancez le serveur avec :
uvicorn whoami:app --host 0.0.0.0 --port 3001
Comme l’implémentation actuelle de l’inspecteur MCP ne gère pas les flux d’autorisation, nous utiliserons l’approche SSE pour configurer le serveur MCP. Nous mettrons à jour le code ici dès que l’inspecteur MCP prendra en charge les flux d’autorisation.
Vous pouvez également utiliser pnpm
ou yarn
si vous préférez.
Créez un fichier nommé whoami.js
et ajoutez le code suivant :
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
import express from 'express';
// Créez un serveur MCP
const server = new McpServer({
name: 'WhoAmI',
version: '0.0.0',
});
// Ajoutez un outil au serveur qui retourne les informations de l’utilisateur courant
server.tool('whoami', async () => {
return {
content: [{ type: 'text', text: JSON.stringify({ error: 'Not authenticated' }) }],
};
});
// Ci-dessous, le code standard issu de la documentation du SDK MCP
const PORT = 3001;
const app = express();
const transports = {};
app.get('/sse', async (_req, res) => {
const transport = new SSEServerTransport('/messages', res);
transports[transport.sessionId] = transport;
res.on('close', () => {
delete transports[transport.sessionId];
});
await server.connect(transport);
});
app.post('/messages', async (req, res) => {
const sessionId = String(req.query.sessionId);
const transport = transports[sessionId];
if (transport) {
await transport.handlePostMessage(req, res, req.body);
} else {
res.status(400).send('No transport found for sessionId');
}
});
app.listen(PORT);
Lancez le serveur avec :
npm start
Inspecter le serveur MCP
Cloner et lancer l’inspecteur MCP
Maintenant que le serveur MCP fonctionne, nous pouvons utiliser l’inspecteur MCP pour vérifier si l’outil whoami
est disponible.
En raison des limites de l’implémentation actuelle, nous avons forké l’inspecteur MCP pour le rendre plus flexible et évolutif pour l’authentification (Authentication) et l’autorisation (Authorization). Nous avons également soumis une pull request au dépôt original pour inclure nos modifications.
Pour lancer l’inspecteur MCP, vous pouvez utiliser la commande suivante (Node.js est requis) :
git clone https://github.com/mcp-auth/inspector.git
cd inspector
npm install
npm run dev
Ensuite, ouvrez votre navigateur et accédez à http://localhost:6274/
(ou à l’URL affichée dans le terminal) pour accéder à l’inspecteur MCP.
Connecter l’inspecteur MCP au serveur MCP
Avant de continuer, vérifiez la configuration suivante dans l’inspecteur MCP :
- Type de transport : Réglez sur
SSE
. - URL : Réglez sur l’URL de votre serveur MCP. Dans notre cas, il s’agit de
http://localhost:3001/sse
.
Vous pouvez maintenant cliquer sur le bouton "Connecter" pour voir si l’inspecteur MCP peut se connecter au serveur MCP. Si tout est correct, vous devriez voir le statut "Connecté" dans l’inspecteur MCP.
Point de contrôle : Exécuter l’outil whoami
- Dans le menu supérieur de l’inspecteur MCP, cliquez sur l’onglet "Outils".
- Cliquez sur le bouton "Lister les outils".
- Vous devriez voir l’outil
whoami
listé sur la page. Cliquez dessus pour ouvrir les détails de l’outil. - Vous devriez voir le bouton "Exécuter l’outil" à droite. Cliquez dessus pour exécuter l’outil.
- Vous devriez voir le résultat de l’outil avec la réponse JSON
{"error": "Not authenticated"}
.
Intégrer avec votre serveur d’autorisation
Pour compléter cette section, plusieurs points sont à prendre en compte :
L’URL de l’émetteur (Issuer) de votre serveur d’autorisation
Il s’agit généralement de l’URL de base de votre serveur d’autorisation, comme https://auth.example.com
. Certains fournisseurs peuvent avoir un chemin comme https://example.logto.app/oidc
, alors assurez-vous de vérifier la documentation de votre fournisseur.
Comment récupérer les métadonnées du serveur d’autorisation
- Si votre serveur d’autorisation est conforme à la spécification OAuth 2.0 Authorization Server Metadata ou à OpenID Connect Discovery, vous pouvez utiliser les utilitaires intégrés de MCP Auth pour récupérer automatiquement les métadonnées.
- Si votre serveur d’autorisation n’est pas conforme à ces standards, vous devrez spécifier manuellement l’URL des métadonnées ou les endpoints dans la configuration du serveur MCP. Consultez la documentation de votre fournisseur pour les endpoints spécifiques.
Comment enregistrer l’inspecteur MCP comme client dans votre serveur d’autorisation
- Si votre serveur d’autorisation prend en charge l’enregistrement dynamique du client, vous pouvez ignorer cette étape car l’inspecteur MCP s’enregistrera automatiquement comme client.
- Si votre serveur d’autorisation ne prend pas en charge l’enregistrement dynamique du client, vous devrez enregistrer manuellement l’inspecteur MCP comme client dans votre serveur d’autorisation.
Comment récupérer les informations d'identité utilisateur et comment configurer les paramètres de la requête d’autorisation
-
Pour les fournisseurs OpenID Connect : généralement, vous devez demander au moins les portées (Scopes)
openid
etprofile
lors de l’initiation du flux d’autorisation. Cela garantira que le jeton d’accès (Access token) retourné par le serveur d’autorisation contient les portées nécessaires pour accéder à l’endpoint userinfo et récupérer les informations d'identité utilisateur.Remarque : certains fournisseurs peuvent ne pas prendre en charge l’endpoint userinfo.
-
Pour les fournisseurs OAuth 2.0 / OAuth 2.1 : consultez la documentation de votre fournisseur pour savoir comment récupérer les informations d'identité utilisateur à l’aide d’un jeton d’accès (Access token) et quels paramètres sont requis pour obtenir ce jeton lors de l’appel du flux d’autorisation.
Bien que chaque fournisseur puisse avoir ses propres exigences spécifiques, les étapes suivantes vous guideront dans le processus d’intégration de l’inspecteur MCP et du serveur MCP avec des configurations spécifiques au fournisseur.
Enregistrer l’inspecteur MCP comme client
- Logto
- Keycloak
- OIDC
- OAuth 2
L’intégration avec Logto est simple puisqu’il s’agit d’un fournisseur OpenID Connect qui prend en charge l’endpoint userinfo standard pour récupérer les informations d'identité utilisateur.
Comme Logto ne prend pas encore en charge l’enregistrement dynamique du client, vous devrez enregistrer manuellement l’inspecteur MCP comme client dans votre tenant Logto :
- Ouvrez votre inspecteur MCP, cliquez sur le bouton "Configuration OAuth". Copiez la valeur Redirect URL (auto-populated), qui devrait ressembler à
http://localhost:6274/oauth/callback
. - Connectez-vous à Logto Console (ou à votre Logto Console auto-hébergée).
- Accédez à l’onglet "Applications", cliquez sur "Créer une application". En bas de la page, cliquez sur "Créer une application sans framework".
- Remplissez les détails de l’application, puis cliquez sur "Créer l’application" :
- Sélectionnez un type d’application : Choisissez "Application monopage".
- Nom de l’application : Entrez un nom pour votre application, par exemple "MCP Inspector".
- Dans la section "Paramètres / URI de redirection", collez la valeur Redirect URL (auto-populated) copiée depuis l’inspecteur MCP. Cliquez ensuite sur "Enregistrer les modifications" dans la barre du bas.
- Dans la carte du haut, vous verrez la valeur "App ID". Copiez-la.
- Retournez dans l’inspecteur MCP et collez la valeur "App ID" dans la section "Configuration OAuth" sous "Client ID".
- Entrez la valeur
{"scope": "openid profile email"}
dans le champ "Auth Params". Cela garantira que le jeton d’accès (Access token) retourné par Logto contient les portées nécessaires pour accéder à l’endpoint userinfo.
Keycloak est une solution open-source de gestion des identités et des accès qui prend en charge le protocole OpenID Connect.
Bien que Keycloak prenne en charge l’enregistrement dynamique du client, son endpoint d’enregistrement ne prend pas en charge CORS, ce qui empêche la plupart des clients MCP de s’enregistrer directement. Nous devrons donc enregistrer notre client manuellement.
Bien que Keycloak puisse être installé de différentes manières (bare metal, kubernetes, etc.), pour ce tutoriel, nous utiliserons Docker pour une configuration rapide et simple.
Configurons une instance Keycloak et adaptons-la à nos besoins :
- Lancez une instance Keycloak avec Docker en suivant la documentation officielle :
docker run -p 8080:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:26.2.4 start-dev
-
Accédez à la console d’administration Keycloak (http://localhost:8080/admin) et connectez-vous avec ces identifiants :
- Nom d’utilisateur :
admin
- Mot de passe :
admin
- Nom d’utilisateur :
-
Créez un nouveau Realm :
- Cliquez sur "Create Realm" en haut à gauche
- Entrez
mcp-realm
dans le champ "Realm name" - Cliquez sur "Create"
-
Créez un utilisateur de test :
- Cliquez sur "Users" dans le menu de gauche
- Cliquez sur "Create new user"
- Remplissez les informations utilisateur :
- Nom d’utilisateur :
testuser
- Prénom et nom peuvent être quelconques
- Nom d’utilisateur :
- Cliquez sur "Create"
- Dans l’onglet "Credentials", définissez un mot de passe et décochez "Temporary"
-
Enregistrez l’inspecteur MCP comme client :
- Ouvrez votre inspecteur MCP, cliquez sur le bouton "Configuration OAuth". Copiez la valeur Redirect URL (auto-populated), qui devrait ressembler à
http://localhost:6274/oauth/callback
. - Dans la console d’administration Keycloak, cliquez sur "Clients" dans le menu de gauche
- Cliquez sur "Create client"
- Remplissez les détails du client :
- Type de client : Sélectionnez "OpenID Connect"
- Client ID : Entrez
mcp-inspector
- Cliquez sur "Next"
- Sur la page "Capability config" :
- Assurez-vous que "Standard flow" est activé
- Cliquez sur "Next"
- Sur la page "Login settings" :
- Collez l’URL de rappel de l’inspecteur MCP précédemment copiée dans "Valid redirect URIs"
- Entrez
http://localhost:6274
dans "Web origins" - Cliquez sur "Save"
- Copiez le "Client ID" (qui est
mcp-inspector
)
- Ouvrez votre inspecteur MCP, cliquez sur le bouton "Configuration OAuth". Copiez la valeur Redirect URL (auto-populated), qui devrait ressembler à
-
De retour dans l’inspecteur MCP :
- Collez le Client ID copié dans le champ "Client ID" de la section "Configuration OAuth"
- Entrez la valeur suivante dans le champ "Auth Params" pour demander les portées nécessaires :
{ "scope": "openid profile email" }
Ceci est un guide générique d’intégration avec un fournisseur OpenID Connect. Consultez la documentation de votre fournisseur pour les détails spécifiques.
Si votre fournisseur OpenID Connect prend en charge l’enregistrement dynamique du client, vous pouvez passer directement à l’étape 8 ci-dessous pour configurer l’inspecteur MCP ; sinon, vous devrez enregistrer manuellement l’inspecteur MCP comme client dans votre fournisseur OpenID Connect :
- Ouvrez votre inspecteur MCP, cliquez sur le bouton "Configuration OAuth". Copiez la valeur Redirect URL (auto-populated), qui devrait ressembler à
http://localhost:6274/oauth/callback
. - Connectez-vous à la console de votre fournisseur OpenID Connect.
- Accédez à la section "Applications" ou "Clients", puis créez une nouvelle application ou un nouveau client.
- Si votre fournisseur demande un type de client, sélectionnez "Application monopage" ou "Client public".
- Après avoir créé l’application, vous devrez configurer l’URI de redirection. Collez la valeur Redirect URL (auto-populated) copiée depuis l’inspecteur MCP.
- Trouvez le "Client ID" ou "Application ID" de la nouvelle application et copiez-le.
- Retournez dans l’inspecteur MCP et collez la valeur "Client ID" dans la section "Configuration OAuth" sous "Client ID".
- Pour les fournisseurs OpenID Connect standards, vous pouvez entrer la valeur suivante dans le champ "Auth Params" pour demander les portées nécessaires à l’accès à l’endpoint userinfo :
{ "scope": "openid profile email" }
Ceci est un guide générique d’intégration avec un fournisseur OAuth 2.0 / OAuth 2.1. Consultez la documentation de votre fournisseur pour les détails spécifiques.
Si votre fournisseur OAuth 2.0 / OAuth 2.1 prend en charge l’enregistrement dynamique du client, vous pouvez passer directement à l’étape 8 ci-dessous pour configurer l’inspecteur MCP ; sinon, vous devrez enregistrer manuellement l’inspecteur MCP comme client dans votre fournisseur OAuth 2.0 / OAuth 2.1 :
- Ouvrez votre inspecteur MCP, cliquez sur le bouton "Configuration OAuth". Copiez la valeur Redirect URL (auto-populated), qui devrait ressembler à
http://localhost:6274/oauth/callback
. - Connectez-vous à la console de votre fournisseur OAuth 2.0 / OAuth 2.1.
- Accédez à la section "Applications" ou "Clients", puis créez une nouvelle application ou un nouveau client.
- Si votre fournisseur demande un type de client, sélectionnez "Application monopage" ou "Client public".
- Après avoir créé l’application, vous devrez configurer l’URI de redirection. Collez la valeur Redirect URL (auto-populated) copiée depuis l’inspecteur MCP.
- Trouvez le "Client ID" ou "Application ID" de la nouvelle application et copiez-le.
- Retournez dans l’inspecteur MCP et collez la valeur "Client ID" dans la section "Configuration OAuth" sous "Client ID".
- Consultez la documentation de votre fournisseur pour savoir comment obtenir des jetons d’accès pour les informations d'identité utilisateur. Vous devrez peut-être spécifier les portées ou paramètres requis pour obtenir le jeton d’accès. Par exemple, si votre fournisseur exige la portée
profile
pour accéder aux informations d'identité utilisateur, vous pouvez entrer la valeur suivante dans le champ "Auth Params" :
{ "scope": "profile" }
Configurer MCP Auth
Dans votre projet serveur MCP, vous devez installer le SDK MCP Auth et le configurer pour utiliser les métadonnées de votre serveur d’autorisation.
- Python
- Node.js
D’abord, installez le paquet mcpauth
:
pip install mcpauth
Ou tout autre gestionnaire de paquets que vous préférez, comme uv
ou poetry
.
D’abord, installez le paquet mcp-auth
:
npm install mcp-auth
MCP Auth nécessite les métadonnées du serveur d’autorisation pour pouvoir s’initialiser. Selon votre fournisseur :
- Logto
- Keycloak
- OIDC
- OAuth 2
L’URL de l’émetteur (Issuer) se trouve sur la page de détails de votre application dans Logto Console, dans la section "Endpoints & Credentials / Issuer endpoint". Elle devrait ressembler à https://my-project.logto.app/oidc
.
- Python
- Node.js
Mettez à jour le fichier whoami.py
pour inclure la configuration MCP Auth :
from mcpauth import MCPAuth
from mcpauth.config import AuthServerType
from mcpauth.utils import fetch_server_config
auth_issuer = '<issuer-endpoint>' # Remplacez par votre endpoint d’émetteur
auth_server_config = fetch_server_config(auth_issuer, type=AuthServerType.OIDC)
mcp_auth = MCPAuth(server=auth_server_config)
Mettez à jour le fichier whoami.js
pour inclure la configuration MCP Auth :
import { MCPAuth, fetchServerConfig } from 'mcp-auth';
const authIssuer = '<issuer-endpoint>'; // Remplacez par votre endpoint d’émetteur
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, { type: 'oidc' }),
});
Nous devons maintenant créer un vérificateur personnalisé de jeton d’accès (Access token) qui ira chercher les informations d'identité de l'utilisateur auprès du serveur d'autorisation en utilisant le jeton d’accès fourni par l’inspecteur MCP.
- Python
- Node.js
import pydantic
import requests
from mcpauth.exceptions import (
MCPAuthTokenVerificationException,
MCPAuthTokenVerificationExceptionCode,
)
from mcpauth.types import AuthInfo
def verify_access_token(token: str) -> AuthInfo:
"""
Vérifie le jeton Bearer fourni en récupérant les informations utilisateur depuis le serveur d'autorisation.
Si le jeton est valide, retourne un objet `AuthInfo` contenant les informations de l'utilisateur.
:param token: Le jeton Bearer reçu de l’inspecteur MCP.
"""
issuer = auth_server_config.metadata.issuer
endpoint = auth_server_config.metadata.userinfo_endpoint # Le fournisseur doit supporter l’endpoint userinfo
if not endpoint:
raise ValueError(
"L’endpoint userinfo n’est pas configuré dans les métadonnées du serveur d’authentification."
)
try:
response = requests.get(
endpoint,
headers={"Authorization": f"Bearer {token}"}, # En-tête standard Bearer token
)
response.raise_for_status() # S’assurer de lever une erreur pour les erreurs HTTP
json = response.json() # Analyse la réponse JSON
return AuthInfo(
token=token,
subject=json.get("sub"), # 'sub' est une revendication standard pour le sujet (ID utilisateur)
issuer=issuer, # Utilise l’émetteur issu des métadonnées
claims=json, # Inclut toutes les revendications (champs JSON) retournées par l’endpoint userinfo
)
# `AuthInfo` est un modèle Pydantic, donc les erreurs de validation signifient généralement que la réponse ne correspond pas
# à la structure attendue
except pydantic.ValidationError as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.INVALID_TOKEN,
cause=e,
)
# Gérer les autres exceptions pouvant survenir lors de la requête
except Exception as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.TOKEN_VERIFICATION_FAILED,
cause=e,
)
import { MCPAuthTokenVerificationError } from 'mcp-auth';
/**
* Vérifie le jeton Bearer fourni en récupérant les informations utilisateur depuis le serveur d'autorisation.
* Si le jeton est valide, retourne un objet `AuthInfo` contenant les informations de l'utilisateur.
*/
const verifyToken = async (token) => {
const { issuer, userinfoEndpoint } = mcpAuth.config.server.metadata;
if (!userinfoEndpoint) {
throw new Error('L’endpoint userinfo n’est pas configuré dans les métadonnées du serveur');
}
const response = await fetch(userinfoEndpoint, {
headers: { Authorization: `Bearer ${token}` },
});
if (!response.ok) {
throw new MCPAuthTokenVerificationError('token_verification_failed', response);
}
const userInfo = await response.json();
if (typeof userInfo !== 'object' || userInfo === null || !('sub' in userInfo)) {
throw new MCPAuthTokenVerificationError('invalid_token', response);
}
return {
token,
issuer,
subject: String(userInfo.sub), // 'sub' est une revendication standard pour le sujet (ID utilisateur)
clientId: '', // L’ID client n’est pas utilisé dans cet exemple, mais peut être défini si besoin
scopes: [],
claims: userInfo,
};
};
L’URL de l’émetteur (Issuer) se trouve dans votre console d’administration Keycloak. Dans votre 'mcp-realm', accédez à la section "Realm settings / Endpoints" et cliquez sur le lien "OpenID Endpoint Configuration". Le champ issuer
dans le document JSON contiendra votre URL d’émetteur, qui devrait ressembler à http://localhost:8080/realms/mcp-realm
.
- Python
- Node.js
Mettez à jour le fichier whoami.py
pour inclure la configuration MCP Auth :
from mcpauth import MCPAuth
from mcpauth.config import AuthServerType
from mcpauth.utils import fetch_server_config
auth_issuer = '<issuer-endpoint>' # Remplacez par votre endpoint d’émetteur
auth_server_config = fetch_server_config(auth_issuer, type=AuthServerType.OIDC)
mcp_auth = MCPAuth(server=auth_server_config)
Mettez à jour le fichier whoami.js
pour inclure la configuration MCP Auth :
import { MCPAuth, fetchServerConfig } from 'mcp-auth';
const authIssuer = '<issuer-endpoint>'; // Remplacez par votre endpoint d’émetteur
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, { type: 'oidc' }),
});
Nous devons maintenant créer un vérificateur personnalisé de jeton d’accès (Access token) qui ira chercher les informations d'identité de l'utilisateur auprès du serveur d'autorisation en utilisant le jeton d’accès fourni par l’inspecteur MCP.
- Python
- Node.js
import pydantic
import requests
from mcpauth.exceptions import (
MCPAuthTokenVerificationException,
MCPAuthTokenVerificationExceptionCode,
)
from mcpauth.types import AuthInfo
def verify_access_token(token: str) -> AuthInfo:
"""
Vérifie le jeton Bearer fourni en récupérant les informations utilisateur depuis le serveur d'autorisation.
Si le jeton est valide, retourne un objet `AuthInfo` contenant les informations de l'utilisateur.
:param token: Le jeton Bearer reçu de l’inspecteur MCP.
"""
issuer = auth_server_config.metadata.issuer
endpoint = auth_server_config.metadata.userinfo_endpoint # Le fournisseur doit supporter l’endpoint userinfo
if not endpoint:
raise ValueError(
"L’endpoint userinfo n’est pas configuré dans les métadonnées du serveur d’authentification."
)
try:
response = requests.get(
endpoint,
headers={"Authorization": f"Bearer {token}"}, # En-tête standard Bearer token
)
response.raise_for_status() # S’assurer de lever une erreur pour les erreurs HTTP
json = response.json() # Analyse la réponse JSON
return AuthInfo(
token=token,
subject=json.get("sub"), # 'sub' est une revendication standard pour le sujet (ID utilisateur)
issuer=issuer, # Utilise l’émetteur issu des métadonnées
claims=json, # Inclut toutes les revendications (champs JSON) retournées par l’endpoint userinfo
)
# `AuthInfo` est un modèle Pydantic, donc les erreurs de validation signifient généralement que la réponse ne correspond pas
# à la structure attendue
except pydantic.ValidationError as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.INVALID_TOKEN,
cause=e,
)
# Gérer les autres exceptions pouvant survenir lors de la requête
except Exception as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.TOKEN_VERIFICATION_FAILED,
cause=e,
)
import { MCPAuthTokenVerificationError } from 'mcp-auth';
/**
* Vérifie le jeton Bearer fourni en récupérant les informations utilisateur depuis le serveur d'autorisation.
* Si le jeton est valide, retourne un objet `AuthInfo` contenant les informations de l'utilisateur.
*/
const verifyToken = async (token) => {
const { issuer, userinfoEndpoint } = mcpAuth.config.server.metadata;
if (!userinfoEndpoint) {
throw new Error('L’endpoint userinfo n’est pas configuré dans les métadonnées du serveur');
}
const response = await fetch(userinfoEndpoint, {
headers: { Authorization: `Bearer ${token}` },
});
if (!response.ok) {
throw new MCPAuthTokenVerificationError('token_verification_failed', response);
}
const userInfo = await response.json();
if (typeof userInfo !== 'object' || userInfo === null || !('sub' in userInfo)) {
throw new MCPAuthTokenVerificationError('invalid_token', response);
}
return {
token,
issuer,
subject: String(userInfo.sub), // 'sub' est une revendication standard pour le sujet (ID utilisateur)
clientId: '', // L’ID client n’est pas utilisé dans cet exemple, mais peut être défini si besoin
scopes: [],
claims: userInfo,
};
};
Le code suivant suppose également que le serveur d’autorisation prend en charge l’endpoint userinfo pour récupérer les informations d'identité utilisateur. Si votre fournisseur ne prend pas en charge cet endpoint, vous devrez consulter la documentation de votre fournisseur pour l’endpoint spécifique et remplacer la variable userinfo endpoint par la bonne URL.
- Python
- Node.js
Mettez à jour le fichier whoami.py
pour inclure la configuration MCP Auth :
from mcpauth import MCPAuth
from mcpauth.config import AuthServerType
from mcpauth.utils import fetch_server_config
auth_issuer = '<issuer-endpoint>' # Remplacez par votre endpoint d’émetteur
auth_server_config = fetch_server_config(auth_issuer, type=AuthServerType.OIDC)
mcp_auth = MCPAuth(server=auth_server_config)
Mettez à jour le fichier whoami.js
pour inclure la configuration MCP Auth :
import { MCPAuth, fetchServerConfig } from 'mcp-auth';
const authIssuer = '<issuer-endpoint>'; // Remplacez par votre endpoint d’émetteur
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, { type: 'oidc' }),
});
Dans certains cas, la réponse du fournisseur peut être mal formée ou ne pas être conforme au format de métadonnées attendu. Si vous êtes certain que le fournisseur est conforme, vous pouvez transpiler les métadonnées via l’option de configuration :
- Python
- Node.js
mcp_auth = MCPAuth(
server=fetch_server_config(
# ...autres options
transpile_data=lambda data: {**data, 'response_types_supported': ['code']}
)
)
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, {
// ...autres options
transpileData: (data) => ({ ...data, response_types_supported: ['code'] }),
}),
});
Si votre fournisseur ne prend pas en charge OpenID Connect Discovery, vous pouvez spécifier manuellement l’URL des métadonnées ou les points de terminaison. Consultez Autres méthodes pour initialiser MCP Auth pour plus de détails.
Nous devons maintenant créer un vérificateur personnalisé de jeton d’accès (Access token) qui ira chercher les informations d'identité de l'utilisateur auprès du serveur d'autorisation en utilisant le jeton d’accès fourni par l’inspecteur MCP.
- Python
- Node.js
import pydantic
import requests
from mcpauth.exceptions import (
MCPAuthTokenVerificationException,
MCPAuthTokenVerificationExceptionCode,
)
from mcpauth.types import AuthInfo
def verify_access_token(token: str) -> AuthInfo:
"""
Vérifie le jeton Bearer fourni en récupérant les informations utilisateur depuis le serveur d'autorisation.
Si le jeton est valide, retourne un objet `AuthInfo` contenant les informations de l'utilisateur.
:param token: Le jeton Bearer reçu de l’inspecteur MCP.
"""
issuer = auth_server_config.metadata.issuer
endpoint = auth_server_config.metadata.userinfo_endpoint # Le fournisseur doit supporter l’endpoint userinfo
if not endpoint:
raise ValueError(
"L’endpoint userinfo n’est pas configuré dans les métadonnées du serveur d’authentification."
)
try:
response = requests.get(
endpoint,
headers={"Authorization": f"Bearer {token}"}, # En-tête standard Bearer token
)
response.raise_for_status() # S’assurer de lever une erreur pour les erreurs HTTP
json = response.json() # Analyse la réponse JSON
return AuthInfo(
token=token,
subject=json.get("sub"), # 'sub' est une revendication standard pour le sujet (ID utilisateur)
issuer=issuer, # Utilise l’émetteur issu des métadonnées
claims=json, # Inclut toutes les revendications (champs JSON) retournées par l’endpoint userinfo
)
# `AuthInfo` est un modèle Pydantic, donc les erreurs de validation signifient généralement que la réponse ne correspond pas
# à la structure attendue
except pydantic.ValidationError as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.INVALID_TOKEN,
cause=e,
)
# Gérer les autres exceptions pouvant survenir lors de la requête
except Exception as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.TOKEN_VERIFICATION_FAILED,
cause=e,
)
import { MCPAuthTokenVerificationError } from 'mcp-auth';
/**
* Vérifie le jeton Bearer fourni en récupérant les informations utilisateur depuis le serveur d'autorisation.
* Si le jeton est valide, retourne un objet `AuthInfo` contenant les informations de l'utilisateur.
*/
const verifyToken = async (token) => {
const { issuer, userinfoEndpoint } = mcpAuth.config.server.metadata;
if (!userinfoEndpoint) {
throw new Error('L’endpoint userinfo n’est pas configuré dans les métadonnées du serveur');
}
const response = await fetch(userinfoEndpoint, {
headers: { Authorization: `Bearer ${token}` },
});
if (!response.ok) {
throw new MCPAuthTokenVerificationError('token_verification_failed', response);
}
const userInfo = await response.json();
if (typeof userInfo !== 'object' || userInfo === null || !('sub' in userInfo)) {
throw new MCPAuthTokenVerificationError('invalid_token', response);
}
return {
token,
issuer,
subject: String(userInfo.sub), // 'sub' est une revendication standard pour le sujet (ID utilisateur)
clientId: '', // L’ID client n’est pas utilisé dans cet exemple, mais peut être défini si besoin
scopes: [],
claims: userInfo,
};
};
Comme mentionné précédemment, OAuth 2.0 ne définit pas de méthode standard pour récupérer les informations d'identité utilisateur. Le code suivant suppose que votre fournisseur dispose d’un endpoint spécifique pour récupérer les informations d'identité utilisateur à l’aide d’un jeton d’accès (Access token). Vous devrez consulter la documentation de votre fournisseur pour l’endpoint spécifique et remplacer la variable userinfo endpoint par la bonne URL.
- Python
- Node.js
Mettez à jour le fichier whoami.py
pour inclure la configuration MCP Auth :
from mcpauth import MCPAuth
from mcpauth.config import AuthServerType
from mcpauth.utils import fetch_server_config
auth_issuer = '<issuer-endpoint>' # Remplacez par votre endpoint d’émetteur
auth_server_config = fetch_server_config(auth_issuer, type=AuthServerType.OAUTH)
mcp_auth = MCPAuth(server=auth_server_config)
Mettez à jour le fichier whoami.js
pour inclure la configuration MCP Auth :
import { MCPAuth, fetchServerConfig } from 'mcp-auth';
const authIssuer = '<issuer-endpoint>'; // Remplacez par votre endpoint d’émetteur
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, { type: 'oauth' }),
});
Dans certains cas, la réponse du fournisseur peut être mal formée ou ne pas être conforme au format de métadonnées attendu. Si vous êtes certain que le fournisseur est conforme, vous pouvez transpiler les métadonnées via l’option de configuration :
- Python
- Node.js
mcp_auth = MCPAuth(
server=fetch_server_config(
# ...autres options
transpile_data=lambda data: {**data, 'response_types_supported': ['code']}
)
)
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, {
// ...autres options
transpileData: (data) => ({ ...data, response_types_supported: ['code'] }),
}),
});
Si votre fournisseur ne prend pas en charge Métadonnées du serveur d’autorisation OAuth 2.0, vous pouvez spécifier manuellement l’URL des métadonnées ou les points de terminaison. Consultez Autres méthodes pour initialiser MCP Auth pour plus de détails.
Nous devons maintenant créer un vérificateur personnalisé de jeton d’accès (Access token) qui ira chercher les informations d'identité de l'utilisateur auprès du serveur d'autorisation en utilisant le jeton d’accès fourni par l’inspecteur MCP.
- Python
- Node.js
import pydantic
import requests
from mcpauth.exceptions import (
MCPAuthTokenVerificationException,
MCPAuthTokenVerificationExceptionCode,
)
from mcpauth.types import AuthInfo
def verify_access_token(token: str) -> AuthInfo:
"""
Vérifie le jeton Bearer fourni en récupérant les informations utilisateur auprès du serveur d'autorisation.
Si le jeton est valide, retourne un objet `AuthInfo` contenant les informations de l'utilisateur.
:param token: Le jeton Bearer reçu de l’inspecteur MCP.
"""
try:
# Le code suivant suppose que votre serveur d'autorisation dispose d'un endpoint pour récupérer les infos utilisateur
# en utilisant le jeton d’accès émis par le flux d'autorisation.
# Adaptez l’URL et les en-têtes selon l’API de votre fournisseur.
response = requests.get(
"https://your-authorization-server.com/userinfo",
headers={"Authorization": f"Bearer {token}"},
)
response.raise_for_status() # S'assurer qu'une erreur est levée pour les erreurs HTTP
json = response.json() # Analyse la réponse JSON
# Le code suivant suppose que la réponse contient un champ 'sub' qui identifie l'utilisateur.
# Vous devrez peut-être l’adapter selon l’API de votre fournisseur.
return AuthInfo(
token=token,
subject=json.get("sub"),
issuer=auth_issuer, # Utilisez l’émetteur configuré
claims=json, # Inclut toutes les revendications (champs JSON) retournées par l’endpoint
)
# `AuthInfo` est un modèle Pydantic, donc les erreurs de validation signifient généralement que la réponse ne correspond pas
# à la structure attendue
except pydantic.ValidationError as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.INVALID_TOKEN,
cause=e,
)
# Gérer les autres exceptions pouvant survenir lors de la requête
except Exception as e:
raise MCPAuthTokenVerificationException(
MCPAuthTokenVerificationExceptionCode.TOKEN_VERIFICATION_FAILED,
cause=e,
)
import { MCPAuthTokenVerificationError } from 'mcp-auth';
/**
* Vérifie le jeton Bearer fourni en récupérant les informations utilisateur auprès du serveur d'autorisation.
* Si le jeton est valide, retourne un objet `AuthInfo` contenant les informations de l'utilisateur.
*/
const verifyToken = async (token) => {
// Le code suivant suppose que votre serveur d'autorisation dispose d'un endpoint pour récupérer les infos utilisateur
// en utilisant le jeton d’accès émis par le flux d'autorisation.
// Adaptez l’URL et les en-têtes selon l’API de votre fournisseur.
const response = await fetch('https://your-authorization-server.com/userinfo', {
headers: { Authorization: `Bearer ${token}` },
});
if (!response.ok) {
throw new MCPAuthTokenVerificationError('token_verification_failed', response);
}
const userInfo = await response.json();
// Le code suivant suppose que la réponse contient un champ 'sub' qui identifie l'utilisateur.
// Vous devrez peut-être l’adapter selon l’API de votre fournisseur.
if (typeof userInfo !== 'object' || userInfo === null || !('sub' in userInfo)) {
throw new MCPAuthTokenVerificationError('invalid_token', response);
}
return {
token,
issuer: authIssuer,
subject: String(userInfo.sub), // Adaptez ceci selon le champ d’ID utilisateur de votre fournisseur
clientId: '', // L’ID client n’est pas utilisé dans cet exemple, mais peut être défini si besoin
scopes: [],
claims: userInfo,
};
};
Mettre à jour le serveur MCP
Nous y sommes presque ! Il est temps de mettre à jour le serveur MCP pour appliquer la route MCP Auth et la fonction middleware, puis faire en sorte que l’outil whoami
retourne les véritables informations d'identité utilisateur.
- Python
- Node.js
@mcp.tool()
def whoami() -> dict[str, Any]:
"""Un outil qui retourne les informations de l’utilisateur courant."""
return (
mcp_auth.auth_info.claims
if mcp_auth.auth_info # Ceci sera renseigné par le middleware Bearer auth
else {"error": "Not authenticated"}
)
# ...
bearer_auth = Middleware(mcp_auth.bearer_auth_middleware(verify_access_token))
app = Starlette(
routes=[
# Ajoutez la route des métadonnées (`/.well-known/oauth-authorization-server`)
mcp_auth.metadata_route(),
# Protégez le serveur MCP avec le middleware Bearer auth
Mount('/', app=mcp.sse_app(), middleware=[bearer_auth]),
],
)
server.tool('whoami', ({ authInfo }) => {
return {
content: [
{ type: 'text', text: JSON.stringify(authInfo?.claims ?? { error: 'Not authenticated' }) },
],
};
});
// ...
app.use(mcpAuth.delegatedRouter());
app.use(mcpAuth.bearerAuth(verifyToken));
Point de contrôle : Exécuter l’outil whoami
avec authentification
Redémarrez votre serveur MCP et ouvrez l’inspecteur MCP dans votre navigateur. Lorsque vous cliquez sur le bouton "Connecter", vous devriez être redirigé vers la page de connexion de votre serveur d’autorisation.
Une fois connecté et de retour dans l’inspecteur MCP, répétez les actions du point de contrôle précédent pour exécuter l’outil whoami
. Cette fois, vous devriez voir les informations d'identité utilisateur retournées par le serveur d’autorisation.
- Python
- Node.js
Consultez le dépôt du SDK MCP Auth Python pour le code complet du serveur MCP (version OIDC).
Consultez le dépôt du SDK MCP Auth Node.js pour le code complet du serveur MCP (version OIDC). Ce répertoire contient les versions TypeScript et JavaScript du code.
Notes de clôture
🎊 Félicitations ! Vous avez terminé avec succès le tutoriel. Récapitulons ce que nous avons fait :
- Mise en place d’un serveur MCP basique avec l’outil
whoami
- Intégration du serveur MCP avec un serveur d’autorisation via MCP Auth
- Configuration de l’inspecteur MCP pour authentifier les utilisateurs et récupérer leurs informations d'identité
Vous pouvez également explorer des sujets avancés, notamment :
- Utiliser JWT (JSON Web Token) pour l’authentification (Authentication) et l’autorisation (Authorization)
- Exploiter les indicateurs de ressource (RFC 8707) pour spécifier les ressources accédées
- Implémenter des mécanismes de contrôle d’accès personnalisés, tels que le contrôle d’accès basé sur les rôles (RBAC) ou le contrôle d’accès basé sur les attributs (ABAC)
N’hésitez pas à consulter d’autres tutoriels et la documentation pour tirer le meilleur parti de MCP Auth.