Passer au contenu principal
L’échange de jeton On-Behalf-Of (OBO) (RFC 8693) permet aux services intermédiaires de préserver l’identité et les autorisations de l’utilisateur lorsqu’ils appellent des API en aval. Lorsqu’une application doit appeler une API en aval, elle peut utiliser :
  • Client Credentials Flow : l’application agit en son propre nom et s’authentifie elle-même. La requête peut avoir été initiée par un utilisateur, mais ce contexte sera perdu. Le service en aval ne connaît que l’identité de l’application appelante.
  • Échange de jeton On-Behalf-Of (OBO) : l’application reçoit un jeton associé aux scopes de l’utilisateur et peut l’échanger contre un nouveau jeton pour appeler des services en aval. Cela préserve l’identité et le contexte de l’utilisateur final d’origine tout au long de la chaîne d’appels.
Par exemple, si un utilisateur déclenche un appel vers le service A, qui appelle ensuite le service B, l’échange de jeton OBO permet au service A d’échanger le jeton d’accès de l’utilisateur contre un nouveau jeton qui :
  • Préserve l’identité et les autorisations de l’utilisateur d’origine
  • Est limité spécifiquement au service B
  • Permet au service B de prendre des décisions d’autorisation en fonction de l’utilisateur final
Les échanges de jeton OBO déclenchent le déclencheur Action post-login, où : Comme dans un flux de connexion standard, les scopes renvoyés pour les appels aux API en aval sont basés sur les stratégies de Role-Based Access Control (RBAC) de l’utilisateur.
Si vous achetez le module complémentaire Auth0 for AI Agents, vous pouvez utiliser la limite de débit maximale de l’Authentication API de votre niveau d’abonnement pour les échanges de jeton OBO. Par exemple, si vous utilisez Private Cloud 100 RPS, vous pouvez dépasser la limite de débit de 30 RPS pour les échanges de jeton OBO et utiliser la pleine capacité de 100 RPS pour vos requêtes d’échange de jeton OBO. La limite de l’Authentication API est partagée et agit comme plafond global pour toutes les requêtes à l’Authentication API, y compris les connexions, les actualisations de jetons et les échanges de jetons combinés. Communiquez avec votre Technical Account Manager pour en savoir plus.

Cas d’utilisation

Les cas d’utilisation courants de l’échange de jetons OBO incluent :
  • des serveurs MCP qui doivent appeler des API propriétaires au nom de l’utilisateur
  • des microservices qui doivent appeler des services en aval au nom de l’utilisateur
Pour permettre à vos applications d’appeler des API tierces au nom de l’utilisateur, utilisez Token Vault.

Fonctionnement

L’échange de jetons OBO permet aux services intermédiaires d’échanger un jeton utilisateur reçu contre un nouveau jeton dont la portée est limitée à un service en aval. Le nouveau jeton préserve l’identité de l’utilisateur d’origine tout en assurant le suivi de la chaîne des services impliqués dans la charge utile du JSON Web Token (JWT).

Exemple : le serveur MCP appelle une API propriétaire

Un utilisateur s’authentifie avec Auth0 auprès d’une application, qui appelle ensuite un serveur MCP, lequel doit à son tour appeler une API propriétaire.

Étape 1 : Authentification de l’utilisateur

Lorsque l’utilisateur se connecte, Auth0 émet un jeton d’accès pour le serveur MCP avec les claims suivants dans le payload du JWT :
{
  "sub": "auth0|user123",
  "aud": "https://mcp-server.example.com",
  "azp": "spa_client_id" // ou "client_id" selon le dialecte du jeton
}
ClaimValeurDescription
subauth0|user123L’identité de l’utilisateur final
audhttps://mcp-server.example.comJeton destiné au serveur MCP
azp (ou client_id selon le profil du jeton d’accès)spa_client_idL’application qui a demandé le jeton

Étape 2 : échange OBO

À l’aide de l’échange de jetons OBO, le serveur MCP présente le jeton de l’utilisateur à Auth0 et demande un jeton d’accès avec le scope de l’API propriétaire. Auth0 émet un nouveau jeton d’accès avec le scope de l’API et les revendications suivantes :
{
  "sub": "auth0|user123",
  "aud": "https://first-party-api.example.com",
  "azp": "mcp_server_client_id", // ou "client_id" selon le dialecte du jeton
  "act": {
    "sub": "mcp_server_client_id",
    "act": {
      "sub": "spa_client_id"
    }
  }
}
RevendicationValeurDescription
subauth0|user123Même identité utilisateur conservée
audhttps://first-party-api.example.comJeton destiné à l’API de première partie
azp (ou client_id selon le profil du jeton d’accès)mcp_server_client_idApplication qui a demandé le jeton (le serveur MCP qui a effectué l’échange)
act{"sub": "mcp_server_client_id",
"act": {"sub": "spa_client_id"}}
Chaîne de délégation montrant tous les acteurs impliqués

La revendication act

La revendication act (acteur) permet de suivre l’ensemble de la chaîne de délégation. Chaque niveau act représente un service dans la chaîne d’appels, et le act.sub le plus externe identifie l’acteur actuel ayant effectué l’échange de jeton. Dans notre exemple :
  • act.sub le plus externe : mcp_server_client_id (le serveur MCP qui vient tout juste d’échanger le jeton)
  • act.sub imbriqué : spa_client_id (l’application d’origine)
La revendication azp doit correspondre à la valeur du act.sub le plus externe et identifier le service qui a effectué l’échange de jeton le plus récemment. Si l’API propriétaire appelle un autre service en aval (https://calendar-api.acme.com), la chaîne de délégation s’étendrait :
{
  "sub": "auth0|user123",
  "aud": "https://calendar-api.acme.com",
  "azp": "first_party_api_client_id",
  "act": {
    "sub": "first_party_api_client_id",
    "act": {
      "sub": "mcp_server_client_id",
      "act": {
        "sub": "spa_client_id"
      }
    }
  }
}
La chaîne de délégation est limitée à cinq niveaux imbriqués. L’échange de jeton OBO échouera si le jeton du sujet comporte déjà cinq niveaux act imbriqués.
400 Bad Request
{
  "error": "invalid_request",
  "error_description": "Delegation chain (`act` claim) depth exceeds the maximum allowed limit of 4"
}
Mettez en cache les jetons d’accès pour toute la durée de vie du jeton au lieu de demander un nouveau jeton pour chaque appel à l’API. Les jetons d’accès peuvent être réutilisés jusqu’à leur expiration; des échanges de jetons répétés gaspillent des ressources, augmentent la latence et peuvent entraîner l’application de limites de débit.

Utilisateur > serveur MCP > flux API

Le diagramme suivant illustre un flux complet d’échange de jeton OBO dans lequel un serveur MCP appelle une API propriétaire au nom de l’utilisateur :
  1. Authentification de l’utilisateur : L’utilisateur s’authentifie auprès de l’application cliente. Le serveur d’autorisation Auth0 émet le jeton A, avec un scope pour le serveur MCP.
  2. Requête initiale : L’application cliente appelle le serveur MCP en transmettant le jeton A dans l’en-tête Authorization: Bearer.
  3. Validation et échange de jeton : Le serveur MCP reçoit le jeton A, le valide et le transmet au point de terminaison /oauth/token du serveur d’autorisation Auth0. À l’aide de l’échange de jetons OBO, le serveur MCP présente le jeton A comme subject_token et demande un nouveau jeton pour l’API propriétaire.
  4. Émission du jeton : Le serveur d’autorisation Auth0 émet le jeton B. Le jeton B a le même sub (ID utilisateur) que le jeton A, mais le aud (audience) correspond maintenant à l’API propriétaire.
  5. Appel au service en aval : Le serveur MCP appelle l’API propriétaire à l’aide du jeton B. L’API valide le jeton B et constate que la requête est légitimement effectuée « au nom de » l’utilisateur d’origine.

Utilisateur > API1 > API2 > API3

Le diagramme suivant illustre le flux de bout en bout d’une chaîne de microservices qui effectue des appels en aval au nom de l’utilisateur :
  1. Authentification de l’utilisateur : L’utilisateur s’authentifie avec succès auprès d’une application cliente. Le serveur d’autorisation Auth0 émet le jeton A, dont le scope est défini pour API1.
  2. Requête initiale : L’application cliente appelle API1 en transmettant le jeton A dans l’en-tête Authorization: Bearer.
  3. API1 délègue à API2 : API1 reçoit le jeton A, le valide, puis l’envoie au point de terminaison /oauth/token du serveur d’autorisation Auth0. À l’aide de l’échange de jetons OBO, API1 présente le jeton A comme subject_token et demande un nouveau jeton pour API2.
  4. Émission du jeton : Le serveur d’autorisation Auth0 accorde à API1 un nouveau jeton d’accès, le jeton B. Le jeton B a le même sub (id utilisateur) que le jeton A, mais le aud (audience) est maintenant API2.
  5. Appel en aval : API1 envoie une requête à API2 à l’aide du jeton B.
  6. API2 délègue à API3 : API2 reçoit le jeton B, le valide, puis l’envoie au point de terminaison /oauth/token du serveur d’autorisation Auth0. À l’aide de l’échange de jetons OBO, API2 présente le jeton B comme subject_token et demande un nouveau jeton pour API3.
  7. Émission du jeton : Le serveur d’autorisation Auth0 accorde à API2 un nouveau jeton d’accès, le jeton C. Le jeton C a le même sub (id utilisateur) que les jetons A et B, mais le aud (audience) est maintenant API3.
  8. Appel en aval : API2 envoie une requête à API3 à l’aide du jeton C. API3 valide le jeton C et constate que la requête est bien effectuée « au nom de » l’utilisateur d’origine.

Prérequis

Seuls les clients d’API personnalisés associées à un serveur de ressources peuvent utiliser l’échange de jetons OBO. Un client d’API personnalisé est liée à un serveur de ressources lorsqu’elle partage le même identifiant. Les clients d’API personnalisés doivent respecter les exigences suivantes :
  • Définissez app_type sur resource_server.
  • Définissez resource_server_identifier sur l’identifiant valide du serveur de ressources, c.-à-d. https://my-api.example.com. Auth0 utilise l’identifiant du serveur de ressources comme paramètre audience dans les appels d’autorisation.
Comme les clients d’API personnalisés sont des applications propriétaires, assurez-vous d’ignorer le consentement de l’utilisateur pour les API auxquelles votre application propriétaire doit accéder.

Créer un client d’API personnalisé

Vous pouvez créer un client d’API personnalisé à l’aide de l’Auth0 Dashboard ou de la Management API.
Pour créer un client d’API personnalisé dans l’Auth0 Dashboard :
  1. Accédez à Applications > APIs et sélectionnez votre API de backend.
Mon API OBO de test
  1. Sélectionnez Add Application et saisissez un nom d’application.
  2. Sélectionnez Add.
Une fois l’application créée avec succès, ouvrez-la en sélectionnant Configure Application, puis faites défiler jusqu’à Application Properties. Le champ Application Type doit être Custom API Client.
Mon API OBO de test

Créer un client grant

Vous devez créer un client grant avec délégation utilisateur entre le client d’API personnalisé et l’API en aval afin d’autoriser l’accès.
  1. Accédez à Applications > Applications et sélectionnez votre client d’API personnalisé.
  2. Sous API Access, repérez votre serveur de ressources (c.-à-d. https://my-api.example.com) et sélectionnez Edit.
  3. Sous User-Delegated Access, sélectionnez Grant Access, puis les autorisations à accorder, ou Always grant all permissions.
  4. Sélectionnez Save.

Configurer l’échange de jetons OBO

Découvrez comment configurer votre client d’API personnalisée pour utiliser l’octroi d’échange de jetons OBO.
  1. Accédez à Applications > Applications et sélectionnez votre client d’API personnalisée.
  2. Sous Token Exchange, activez On-Behalf-Of Token Exchange.
  3. Sélectionnez Save.
Mon API OBO de test

Effectuer l’échange de jetons OBO

Pour effectuer l’échange de jetons OBO, vous pouvez utiliser auth0-api-js, auth0_api_python ou l’API d’authentification.
Mettez en cache les jetons d’accès pendant toute leur durée de validité au lieu de demander un nouveau jeton pour chaque appel d’API. Les jetons d’accès peuvent être réutilisés jusqu’à leur expiration ; des échanges de jetons répétés gaspillent des ressources, augmentent la latence et peuvent vous faire atteindre les limites de débit.
Avant de commencer, assurez-vous d’avoir installé la bibliothèque auth0-api-js et ses dépendances.Commencez par initialiser ApiClient avec les identifiants de votre serveur MCP :
import { ApiClient } from '@auth0/auth0-api-js';

const apiClient = new ApiClient({
  domain: 'YOUR_AUTH0_DOMAIN',
  audience: 'YOUR_MCP_SERVER_AUDIENCE',
  clientId: 'YOUR_CLIENT_ID',
  clientSecret: 'YOUR_CLIENT_SECRET',
});
Ensuite, utilisez la méthode getTokenOnBehalfOf() pour procéder à l’échange de jetons :
const result = await apiClient.getTokenOnBehalfOf(accessToken, {
  audience: 'YOUR_DOWNSTREAM_API_AUDIENCE',
  scope: 'read:private',  // Facultatif
});
getTokenOnBehalfOf() renvoie un objet contenant :
  • accessToken : le nouveau jeton pour votre API en aval
  • scope : les scopes accordés
  • expiresIn : le délai d’expiration du jeton, en secondes

Prise en charge des organisations

Lorsqu’un utilisateur s’authentifie dans le cadre d’une organisation, le jeton d’accès comprend une revendication org_id. L’échange de jetons OBO préserve ce contexte organisationnel tout au long de la chaîne de délégation. Lorsque Auth0 reçoit une demande d’échange de jetons OBO avec un jeton d’accès associé à une organisation, il valide :
  • que org_id existe dans votre locataire
  • que l’utilisateur (identifié par sub) est membre de cette organisation
Si la validation échoue, Auth0 rejette la demande d’échange de jetons. Si elle réussit, Auth0 émet un nouveau jeton d’accès qui :
  • contient la même revendication org_id que le jeton d’origine
  • applique les mêmes politiques RBAC propres à l’organisation
  • rend le contexte organisationnel disponible dans le déclencheur Actions post-login au moyen de la propriété event.organization