Passer au contenu principal

Autorisation gérée par l'entreprise avec ID-JAG

Ce guide explique l'Enterprise-Managed Authorization, une extension de la spécification d'autorisation MCP pour les entreprises : le fournisseur d'identité d'entreprise (IdP) décide quels serveurs MCP un employé peut utiliser, et le client MCP obtient ses jetons sans connexion via le navigateur à chaque serveur. Casdoor assume l'un ou l'autre rôle :

  • Le serveur d'autorisation des serveurs MCP : Casdoor accepte les ID-JAGs d'un IdP d'entreprise auquel une organisation fait confiance.
  • L'IdP d'entreprise : Casdoor émet des ID-JAG pour les serveurs MCP dont le serveur d'autorisation lui fait confiance.

Objectifs d'apprentissage​

  • Comprendre le flux et ce qu'est un ID-JAG.
  • Permettre à une organisation de Casdoor de faire confiance aux ID-JAG d'un IdP d'entreprise.
  • Émettre des ID-JAG depuis Casdoor.

Prérequis​

  • Accès administrateur global à la console d'administration Casdoor
  • Un client MCP qui prend en charge l'extension, par exemple Claude Team ou Enterprise avec Okta Cross App Access

Comment ça fonctionne​

Un ID-JAG (Identity Assertion JWT Authorization Grant) est un JWT de courte durée signé par l'IdP. Il indique : cet utilisateur peut utiliser ce client sur ce serveur d'autorisation. Il est défini dans draft-ietf-oauth-identity-assertion-authz-grant, et l'extension MCP io.modelcontextprotocol/enterprise-managed-authorization s'appuie dessus. Voir Enterprise-Managed Authorization.

L'utilisateur ne voit jamais la page de connexion de Casdoor. Lorsque l'IdP bloque l'utilisateur, par exemple après son départ de l'entreprise, le client ne reçoit aucun nouveau ID-JAG, et donc aucun nouveau jeton d'accès.

Accepter les ID-JAG dans Casdoor​

Faire confiance à l'IdP​

  1. Dans la console d'administration de Casdoor, allez dans User Management > Organizations et ouvrez l'organisation des utilisateurs, par exemple acme.

  2. Optionnellement, activez Use organization issuer, afin que l'organisation ait son propre émetteur, https://your-casdoor.com/orgs/acme. Sinon, l'émetteur est celui global, https://your-casdoor.com.

  3. Sous Trusted ID-JAG issuers, ajoutez une ligne :

    ColumnValue
    IssuerL'iss des ID-JAG, par exemple https://acme.okta.com
    JWKS URLLe jeu de clés de l'IdP. Si vous le laissez vide, Casdoor lit jwks_uri depuis <issuer>/.well-known/openid-configuration
    UserComment trouver l'utilisateur dans l'organisation : {email} (par défaut) utilise la revendication email, {sub} la revendication sub, tout autre {claim} cette revendication. Casdoor la compare au nom d'utilisateur, à l'e-mail, au téléphone et à l'ID
  4. Enregistrez l'organisation. Seul un administrateur global peut modifier les émetteurs de confiance.

Dans l'IdP, donnez à Casdoor l'émetteur de l'organisation comme audience des ID-JAG, et les URL des serveurs MCP comme ressources. Pour un serveur derrière la passerelle MCP, cela correspond à https://your-casdoor.com/api/server/acme/<server-name>.

Permettre au client d'utiliser le grant​

Le client échange l'ID-JAG au point de terminaison du jeton avec le grant JWT bearer (urn:ietf:params:oauth:grant-type:jwt-bearer), donc le type de grant doit être autorisé pour son application :

  • Claude : Son document de métadonnées d'ID client https://claude.ai/oauth/mcp-oauth-client-metadata liste le grant. Activez Enable dynamic client registration pour l'organisation, afin que Casdoor accepte le document. Voir Connecter Claude.
  • Une application que vous créez : Ajoutez JWT Bearer à ses Grant types.

Ce que le client envoie​

curl -X POST https://your-casdoor.com/api/login/oauth/access_token \
-d grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer \
-d client_id=<client-id> \
-d client_secret=<client-secret> \
-d assertion=<ID-JAG>

Casdoor répond avec un jeton d'accès dont l'audience est la resource de l'ID-JAG :

{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 604800,
"scope": "openid profile"
}

Ce que Casdoor vérifie​

VérificationRègle
TypeL'en-tête JWT a typ: oauth-id-jag+jwt. Les autres assertions passent par le grant JWT bearer ordinaire
ClientUn client confidentiel s'authentifie, avec son secret client ou private_key_jwt. Un client public basé sur un document de métadonnées d'ID client, comme Claude, n'a pas de secret et envoie uniquement client_id
Audienceaud est l'émetteur d'une organisation avec son propre émetteur, ou l'émetteur global, qui représente l'organisation de l'application du client
Émetteur et signatureiss est un émetteur de confiance de cette organisation, et la clé portant le kid de l'en-tête dans son JWKS vérifie la signature
Durée de vieexp et iat sont présents et valides, avec une minute de tolérance
Liaison clientclient_id est égal à l'ID client du client qui l'échange
Usage uniqueCasdoor accepte chaque jti d'un émetteur une seule fois
UtilisateurL'utilisateur trouvé via User existe dans l'organisation, n'est pas interdit, et peut se connecter à l'application du client
ScopeUn scope dans la requête doit être un sous-ensemble du scope de l'ID-JAG. Sans scope, le jeton reçoit le scope de l'ID-JAG
ResourceLa resource, si présente, devient l'audience du jeton d'accès

Un client qui s'est enregistré lui-même (DCR) ou utilise un document de métadonnées d'ID client ne peut utiliser le grant JWT bearer qu'avec un ID-JAG.

Erreurs​

ErrorCause
invalid_clientUn client confidentiel ne s'est pas authentifié
invalid_grantL'ID-JAG a échoué à l'une des vérifications : mauvaise audience, émetteur non fiable, signature invalide, expiré, émis à un autre client, déjà utilisé, ou l'utilisateur n'existe pas
invalid_scopeLa requête demande un scope que l'ID-JAG n'accorde pas
invalid_targetLa resource de l'ID-JAG n'est pas une URI absolue
unsupported_grant_typeJWT Bearer ne figure pas parmi les types d'autorisation de l'application du client

Les métadonnées du serveur d'autorisation annoncent la prise en charge : grant_types_supported contient urn:ietf:params:oauth:grant-type:jwt-bearer, et authorization_grant_profiles_supported contient urn:ietf:params:oauth:grant-profile:id-jag.

Émettre des ID-JAG depuis Casdoor​

Lorsque Casdoor est le fournisseur d'identité (IdP) de l'entreprise, un client échange le jeton d'identification (ID token) de l'utilisateur contre un ID-JAG sur le point de terminaison des jetons de Casdoor, via l'échange de jetons (RFC 8693) :

curl -X POST https://your-casdoor.com/api/login/oauth/access_token \
-d grant_type=urn:ietf:params:oauth:grant-type:token-exchange \
-d client_id=<client-id> \
-d client_secret=<client-secret> \
-d requested_token_type=urn:ietf:params:oauth:token-type:id-jag \
-d subject_token=<ID token of the user> \
-d subject_token_type=urn:ietf:params:oauth:token-type:id_token \
-d audience=https://mcp-as.example.com \
-d resource=https://mcp.example.com/mcp \
-d scope="openid profile"
{
"issued_token_type": "urn:ietf:params:oauth:token-type:id-jag",
"access_token": "eyJ0eXAiOiJvYXV0aC1pZC1qYWcrand0Ii...",
"token_type": "N_A",
"expires_in": 300,
"scope": "openid profile"
}

Configurez-le comme suit :

  1. Ajoutez Token Exchange aux Grant types de l'application du client.
  2. Enregistrez le serveur MCP sur la page LLM AI > MCP Servers de l'organisation de l'utilisateur, avec son URL comme resource, et sélectionnez une Application qui le représente. Sans resource, Casdoor trouve l'application grâce à l'audience, sous forme d'ID client ou de nom d'application.
  3. Accordez l'accès aux utilisateurs : ajoutez une permission avec Resource type Application, l'application du serveur comme ressource, et Effect Allow. Casdoor n'émet un ID-JAG qu'à un utilisateur couvert par une permission Allow, donc une application à laquelle personne n'a accès reste fermée.

L'ID-JAG est valide pendant 5 minutes. Son aud est l'audience de la requête, client_id est l'ID client de l'application demanderesse, et il porte l'email de l'utilisateur, la resource et le scope. Le serveur d'autorisation du serveur MCP doit faire confiance à l'émetteur de Casdoor, et le client doit utiliser le même ID client là-bas, par exemple l'URL de son document de métadonnées d'ID client.

Voir aussi​