Passer au contenu principal

Placer les serveurs MCP derrière la passerelle MCP de Casdoor, de bout en bout

Ce guide présente un exemple complet : une entreprise publie un serveur MCP à destination de ses employés, qui l'utilisent depuis ChatGPT, Claude, Cursor et VS Code. Casdoor agit à la fois comme passerelle devant le serveur et comme serveur d'autorisation qui authentifie les utilisateurs. Le serveur MCP lui-même n'a besoin d'aucun code OAuth 2.0.


Objectifs d'apprentissage​

  • Préparer une organisation afin que les clients MCP s'y enregistrent et s'y connectent.
  • Enregistrer un serveur MCP dans Casdoor et définir qui peut l'utiliser et quels outils sont accessibles.
  • Connecter les quatre clients MCP courants.
  • Servir plusieurs organisations depuis une seule instance Casdoor.
  • Vérifier, auditer et révoquer les accès.

Prérequis​

  • Une instance Casdoor accessible depuis Internet via HTTPS, par exemple https://auth.example.com. Les connecteurs personnalisés de ChatGPT et Claude y accèdent depuis le cloud.
  • Un serveur MCP utilisant le transport Streamable HTTP, par exemple https://tickets.example.com/mcp, éventuellement protégé par un jeton bearer statique
  • Accès administrateur global à la console d'administration Casdoor

L'exemple​

Acme exploite un serveur MCP pour son système de tickets. Acme souhaite que :

  • Les employés se connectent avec leur compte Acme, via les méthodes de connexion déjà configurées dans Casdoor.
  • Seule l'équipe support puisse utiliser le serveur.
  • Personne ne puisse appeler l'outil delete_ticket via un client IA.
  • Le jeton API propre au serveur ne quitte jamais Casdoor.
  • Un administrateur puisse voir et révoquer chaque client.

Étape 1 : préparer l'organisation​

  1. Dans la console d'administration Casdoor, allez dans User Management > Organizations et ouvrez acme.
  2. Activez Use organization issuer. L'organisation devient son propre serveur d'autorisation, avec l'émetteur https://auth.example.com/orgs/acme et le document de découverte https://auth.example.com/.well-known/oauth-authorization-server/orgs/acme. Les clients MCP qui découvrent cet émetteur s'enregistrent dans acme et authentifient les utilisateurs sur la page de connexion de acme.
  3. Activez Enable dynamic client registration. Cela permet aux clients de s'identifier avec un document de métadonnées d'ID client (Claude, VS Code, ChatGPT) ou de s'enregistrer eux-mêmes (Cursor, anciens clients). Seul un administrateur global peut modifier ce paramètre.
  4. Enregistrez l'organisation.

Sans Use organization issuer, la passerelle nomme l'émetteur global de Casdoor comme serveur d'autorisation, et les clients s'enregistrent dans built-in. Activez-le pour toute organisation autre que built-in qui publie des serveurs MCP.

Étape 2 : définir qui peut utiliser le serveur​

La passerelle autorise l'accès aux utilisateurs de l'organisation du serveur qui ont le droit de se connecter à l'application du serveur.

  1. Allez dans Identity > Applications et ajoutez une application dans acme, par exemple app-tickets. Elle n'a pas besoin d'URL de redirection : les clients MCP ne se connectent pas à elle, elle ne porte que les règles d'accès.
  2. Pour autoriser uniquement l'équipe support, allez dans Authorization > Permissions et ajoutez une permission dans acme :
    • Resource type : Application
    • Resources : app-tickets
    • Groups ou Roles : l'équipe support
    • Actions: Read, Effect: Allow

Sans aucune autorisation sur l'application, chaque utilisateur de acme peut utiliser le serveur. Les administrateurs de acme et les administrateurs globaux peuvent toujours l'utiliser.

Étape 3 : enregistrer le serveur MCP​

  1. Accédez à LLM AI > MCP Servers et ajoutez un serveur dans acme:

    ChampValeur
    Nametickets
    URLhttps://tickets.example.com/mcp
    Applicationapp-tickets
    Access tokenLe jeton API du serveur de tickets, s'il en nécessite un
  2. Enregistrez le serveur, puis sélectionnez Sync sous Tool. Casdoor récupère la liste des outils du serveur.

  3. Bloquez delete_ticket et enregistrez. La passerelle répond à un appel vers un outil bloqué, ou vers un outil qui n'est pas dans la liste, par une erreur et ne le transmet pas.

  4. Copiez l'Base URL: https://auth.example.com/api/server/acme/tickets. C'est l'URL que les utilisateurs ajoutent à leurs clients MCP.

La passerelle supprime l'en-tête Cookie et l'en-tête Authorization de l'utilisateur de chaque requête, et envoie à la place l'Access token du serveur. Casdoor ne renvoie jamais le jeton dans ses réponses API.

note

Pour un serveur d'une organisation autre que built-in, l'URL doit être une adresse Internet publique: la passerelle refuse d'atteindre des adresses privées et bouclées pour le compte d'un tenant. Pour publier un serveur MCP sur votre réseau interne, enregistrez-le dans built-in.

Étape 4 : vérifier la chaîne de découverte​

Chaque client MCP suit la même chaîne. Vérifiez-la avec curl avant de connecter un client:

curl -i -X POST https://auth.example.com/api/server/acme/tickets

Casdoor répond HTTP 401 et nomme les métadonnées de ressource protégée de ce serveur:

WWW-Authenticate: Bearer realm="casdoor", resource_metadata="https://auth.example.com/.well-known/oauth-protected-resource/api/server/acme/tickets"
curl https://auth.example.com/.well-known/oauth-protected-resource/api/server/acme/tickets
{
"resource": "https://auth.example.com/api/server/acme/tickets",
"authorization_servers": ["https://auth.example.com/orgs/acme"],
"bearer_methods_supported": ["header"],
"scopes_supported": ["openid", "profile", "email", "offline_access"]
}
curl https://auth.example.com/.well-known/oauth-authorization-server/orgs/acme

Dans ce document, vérifiez:

  • issuer est https://auth.example.com/orgs/acme, la même valeur que dans authorization_servers.
  • client_id_metadata_document_supported est true, et registration_endpoint se termine par ?organization=acme.
  • token_endpoint_auth_methods_supported contient none, et code_challenge_methods_supported contient S256.

Étape 5 : connecter les clients​

Chaque utilisateur ajoute l'URL de la passerelle à son client et se connecte avec son compte Acme.

ClientOù ajouter le serveurComment il s'identifieGuide
ChatGPTPlugins > + > Add custom MCP serverCIMD https://chatgpt.com/oauth/client.jsonConnecter ChatGPT
Claude Desktop, claude.aiCustomize > Connectors > Add custom connectorCIMD https://claude.ai/oauth/mcp-oauth-client-metadataConnecter Claude
Claude Codeclaude mcp add --transport http tickets <url>CIMD https://claude.ai/oauth/claude-code-client-metadataConnecter Claude
Cursor~/.cursor/mcp.jsonDCRConnecter Cursor
VS Code.vscode/mcp.jsonCIMD https://vscode.dev/oauth/client-metadata.jsonConnecter VS Code

Par exemple, dans Cursor:

{
"mcpServers": {
"tickets": {
"url": "https://auth.example.com/api/server/acme/tickets"
}
}
}

Et dans VS Code:

{
"servers": {
"tickets": {
"type": "http",
"url": "https://auth.example.com/api/server/acme/tickets"
}
}
}

Un client qui utilise un document de métadonnées d'ID client obtient une application dans Casdoor, avec son URL comme ID client, le tag cimd, et un nom commençant par cimd_. Un client qui s'enregistre lui-même obtient une application par enregistrement, avec le tag dcr. Vous ne créez pas d'applications pour les clients.

Ce qui protège le serveur​

VérificationOùCe qui se passe sinon
Le jeton appartient à un utilisateur de acmePasserelleHTTP 401
L'utilisateur peut se connecter à app-ticketsPasserelleHTTP 401
Le jeton a été émis pour ce serveur (RFC 8707)PasserelleHTTP 401: "The access token is for another resource"
L'outil est dans la liste et autoriséPasserelleErreur JSON-RPC, l'appel n'est pas transmis
Le client est un client qui s'est enregistré lui-mêmeToutes les APISes jetons ne peuvent appeler que le flux de connexion, /api/userinfo, /api/mcp, et /api/server/*, jamais les API de gestion

Les clients demandent le jeton avec resource=https://auth.example.com/api/server/acme/tickets, et Casdoor met cette URL dans la revendication aud. Un jeton pour un autre serveur MCP, même de la même organisation, ne fonctionne pas ici, donc un serveur malveillant ne peut pas rejouer les jetons qu'il reçoit.

Servir plusieurs organisations​

Une instance Casdoor peut publier des serveurs MCP pour plusieurs organisations, par exemple les clients d'un SaaS. Répétez les étapes 1 à 3 pour chaque organisation. Ensuite :

  • Chaque organisation a son propre émetteur (issuer), sa page de connexion, ses utilisateurs et ses permissions. Un utilisateur de globex ne peut pas se connecter sur la page de acme et ne peut pas utiliser les serveurs de acme.
  • Les documents de métadonnées d'ID client de ChatGPT, Claude et VS Code possèdent chacun une URL unique, utilisée par toutes les organisations. Casdoor conserve une application partagée par URL dans built-in et la sert comme application de l'organisation vers laquelle l'utilisateur se connecte. Chaque organisation doit toujours activer Enable dynamic client registration pour accepter ces clients.
  • Les jetons portent l'émetteur de l'organisation de l'utilisateur, également après un renouvellement.
  • Un client qui s'enregistre lui-même (DCR) s'enregistre dans l'organisation du document de découverte, via le paramètre organization du point de terminaison d'enregistrement.

Vérifier, auditer et révoquer​

  • Clients : Identity > Applications liste les clients avec les tags cimd et dcr. Supprimez une application dcr_ pour retirer un enregistrement.
  • Tokens : Auditing > Tokens liste chaque jeton avec son utilisateur, son application, son scope et sa ressource. Supprimez un jeton pour couper immédiatement l'accès au client.
  • Users : Interdisez un utilisateur, et ses jetons cessent de fonctionner à la passerelle dès la prochaine requête.
  • Tools : Bloquez un outil sur la page de modification du serveur. La modification prend effet lors du prochain appel.

Permettre aux utilisateurs d'entreprise d'éviter le navigateur​

Lorsque les employés d'une organisation se connectent via un fournisseur d'identité d'entreprise tel que Okta, les clients prenant en charge Enterprise-Managed Authorization (Claude Team and Enterprise) peuvent obtenir le jeton de la passerelle sans connexion via le navigateur : le fournisseur d'identité émet un ID-JAG, et Casdoor l'échange contre un jeton d'accès. Voir Enterprise-managed authorization.

Dépannage​

La passerelle répond 401 après la connexion​

  • Le serveur n'a pas d'Application. Sans cela, seuls les administrateurs peuvent utiliser le serveur. Sélectionnez une application, voir Step 2.
  • Une permission sur l'application exclut l'utilisateur.
  • L'utilisateur appartient à une autre organisation que le serveur.
  • Le client a demandé le jeton pour une autre ressource. Vérifiez la revendication aud du jeton : elle doit correspondre à l'URL de la passerelle.

Le client connecte les utilisateurs sur la mauvaise organisation​

Use organization issuer est désactivé, donc les métadonnées de ressource protégée nomment l'émetteur global. Activez-le, puis reconnectez le client.

"client ID metadata documents are not accepted"​

Enable dynamic client registration est désactivé pour l'organisation. Casdoor doit également pouvoir atteindre l'URL du document du client via Internet.

La passerelle répond 502​

Casdoor ne peut pas atteindre l'URL du serveur. Vérifiez l'URL et, pour une organisation autre que built-in, assurez-vous qu'il s'agit d'une adresse publique.

Voir aussi​