> ## Documentation Index
> Fetch the complete documentation index at: https://auth0.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Appeler des API internes au nom d'un utilisateur

> Découvrez comment appeler une API protégée par Auth0 depuis votre serveur MCP.

Auth0 met en œuvre l’échange de jetons On-Behalf-Of (OBO) ([RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html)) afin de permettre aux serveurs MCP de préserver l’identité et les autorisations de l’utilisateur lorsqu’ils appellent des API en aval. Dans le flux d’échange de jetons OBO, le serveur MCP joue un double rôle : celui de serveur de ressources lorsqu’il reçoit des requêtes du client, et celui de client lorsqu’il appelle votre API en aval au nom de l’utilisateur.

Pour appeler des API internes au nom d’un utilisateur, le serveur MCP doit échanger le jeton d’accès Auth0 reçu du client MCP contre un nouveau jeton d’accès destiné à un public différent. Le public du jeton d’origine est le serveur MCP, alors que celui du nouveau jeton est votre API en aval.

![Diagramme MCP](https://mintlify.s3.us-west-1.amazonaws.com/auth0/docs/images/ai/mcp/mcp_call_api_obo_exchange_light.png)

À la fin de ce Démarrage rapide, vous disposerez des éléments suivants :

* Un serveur MCP qui appelle vos API protégées au nom d’utilisateurs authentifiés grâce à l’échange de jetons OBO
* La vérification et l’échange de jetons à l’aide de la bibliothèque `@auth0/auth0-api-js` (JavaScript) ou `auth0-api-python` (Python)
* Un exemple fonctionnel illustrant le flux complet d’échange de jetons OBO, du client à l’API en aval, en passant par le serveur MCP

## Prerequisites

> **1. Create or log in to your Auth0 account**
>
> To continue with this quickstart, you need to have an [Auth0 account](https://auth0.com/signup).

> **2. Enable the Resource Parameter Compatibility Profile and Include Issuer in Authorization Responses**
>
> To use the `resource` parameter in your access tokens and the `iss` claim to identify your authorization server, you need to enable two toggles in the [Auth0 Dashboard](https://manage.auth0.com/dashboard/):
>
> 1. Navigate to **Settings** on the left sidebar.
> 2. Select [**Advanced**](https://manage.auth0.com/dashboard/#/tenant/advanced) in the top right corner.
> 3. Scroll down to the **Settings** section and enable the following toggles:
>    * **Resource Parameter Compatibility Profile**: Enables support for the `resource` parameter in authorization requests, allowing access tokens to be scoped to a specific API.
>    * **Include Issuer in Authorization Responses**: Includes the `iss` parameter identifying the authorization server in authorization responses, helping clients defend against mix-up attacks.

> **3. Install the Auth0 CLI**
>
> This guide uses [Auth0 CLI](https://auth0.github.io/auth0-cli/) to configure an Auth0 tenant for secure MCP tool access.
>
> 1. Follow the [Auth0 CLI installation instructions](https://auth0.github.io/auth0-cli/).
> 2. Log in to your account with the Auth0 CLI:
>
> ```shell wrap lines theme={null}
> auth0 login --scopes "read:client_grants,create:client_grants,delete:client_grants,read:clients,create:clients,update:clients,read:resource_servers,create:resource_servers,update:resource_servers,read:roles,create:roles,update:roles,update:tenant_settings,read:connections,update:connections"
> ```
>
> Confirm you are in the correct tenant by double-checking the tenant domain in the terminal, or run the command below:
>
> ```shell theme={null}
> auth0 tenants list
> ```
>
> If more than one tenant is configured, the default tenant will be indicated by an arrow.

> **4. Install jq**
>
> To simplify the process of interacting with the Auth0 CLI, we recommend installing [jq](https://jqlang.org/download/). This will allow you to easily parse JSON responses from the CLI.
>
> **macOS**
>
> brew install jq
>
> **Linux**
>
> sudo apt-get install jq
>
> **Windows**
>
> choco install jq

## Configurer les paramètres du locataire

> **1. Promote the connection to a domain-level connection**
>
> To allow third-party clients like MCP Inspector to use a connection such as a username-and-password database or a social connection, you need to promote the connection to a domain-level connection. [Learn more about configuring third-party applications](https://auth0.com/docs/get-started/applications/third-party-applications/configure-third-party-applications.md).
>
> **1. List Your Connection**
>
> List your connections to get their IDs
>
> ```shell theme={null}
> auth0 api get connections
> ```
>
> **2. Choose Your Connections**
>
> From the list, identify which connections you want to use for the MCP server and copy the ID.
>
> * For the username-and-password database, look for the connection with the strategy `auth0`.
> * For the Google social connection, look for the connection with the strategy `google-oauth2`.
>
> **3. Upgrade the Connection to Domain-Level**
>
> For each of those specific connection IDs, run the following command to mark it as a domain-level connection. Replace `YOUR_CONNECTION_ID` with the actual ID (e.g., `con_XXXXXXXXXXXXXXXX`).
>
> ```shell wrap lines theme={null}
> auth0 api patch connections/YOUR_CONNECTION_ID --data '{"is_domain_connection": true}'
> ```

> **2. Create roles**
>
> The sample application in this quickstart is prepared to show different tools depending on the role of a given user. For example, a Tool Administrator will have access to different tools than a Tool User.
>
> Let's create roles that allow you to control which users can access which tools.
>
> For each role you need (e.g., "Tool Administrator", "Tool User"), run the create command as below.
>
> ```shell wrap lines theme={null}
> # Example for an admin role
> auth0 roles create --name "Tool Administrator" --description "Grants access to all MCP tools"
>
> # Example for a basic user role
> auth0 roles create --name "Tool User" --description "Grants access to basic MCP tools"
> ```
>
> Save the IDs from the output (they start with `rol_`), as you'll need them in a later step to assign permissions and users to these roles.

> **3. Assign roles to users**
>
> Find users and assign them to the roles. You can search by their email address:
>
> ```shell wrap lines theme={null}
> auth0 users search --query "email:\"example@google.com\""
> ```
>
> Copy the user ID (`USERID`) from the last command's output, then assign the role to the user:
>
> ```shell wrap lines theme={null}
> auth0 users roles assign "USER_ID_HERE" --roles "YOUR_ROLE_ID_HERE"
> ```

## Configurer les applications et les API Auth0

En raison de son double rôle, le serveur MCP nécessite deux configurations dans Auth0 :

1. En tant que serveur de ressources : une API appelée par le client MCP
2. En tant que client : une application capable d'échanger des jetons pour appeler des API en aval

Configurons maintenant ces deux éléments.

### Créer une API pour représenter votre serveur MCP

An MCP server is treated just like any other [API](https://auth0.com/docs/get-started/apis.md) in your Auth0 tenant, which means you can use the same access control, scoping, and authorization features. The API (also known as a Resource Server) represents your protected MCP Server.

Run the following command to [create an API](https://auth0.com/docs/get-started/auth0-overview/set-up-apis.md) in Auth0:

```shell wrap lines theme={null}
auth0 api post resource-servers --data '{
  "identifier": "http://localhost:3001/",
  "name": "MCP Tools API",
  "signing_alg": "RS256",
  "token_dialect": "rfc9068_profile_authz",
  "enforce_policies": true,
  "scopes": [
    {"value": "tool:whoami", "description": "Access the WhoAmI tool"},
    {"value": "tool:greet", "description": "Access the Greeting tool"}
  ]
}'
```

Note that `rfc9068_profile_authz` is used as the [token dialect](https://auth0.com/docs/get-started/apis/enable-role-based-access-control-for-apis.md#token-dialect-options) to include the `permissions` claim in the access token, which can be useful for the API to check user permissions without making additional calls.

For more details on protecting APIs with Auth0, check our [quickstarts](https://auth0.com/docs/quickstarts.md#backend%2Fapi).

> **Assign permissions to roles**
>
> After creating the API and roles, assign the API permissions to the roles.
>
> ```shell wrap lines theme={null}
> # Example for admin role (all scopes)
> auth0 roles permissions add YOUR_ADMIN_ROLE_ID --api-id "http://localhost:3001/" --permissions "tool:whoami,tool:greet"
>
> # Example for user role (one scope)
> auth0 roles permissions add YOUR_USER_ROLE_ID --api-id "http://localhost:3001/" --permissions "tool:whoami"
> ```
>
> Replace `YOUR_ADMIN_ROLE_ID` and `YOUR_USER_ROLE_ID` with the role IDs you saved when creating the roles.

### Créer une application pour votre serveur MCP

Créez une application qui permet à votre serveur MCP d'agir comme client pour l'échange de jetons OBO. Cette application doit :

* Avoir le même identifiant que l'API de votre serveur MCP (`resource_server_identifier`)
* Utiliser `app_type: resource_server` pour la lier au serveur MCP
* Activer l'échange de jetons OBO dans la configuration `token_exchange`

La commande suivante crée une application liée à votre serveur MCP, avec l'échange de jetons OBO activé :

```shell wrap lines theme={null}
auth0 api post clients --data '{
  "name": "MCP Server Client",
  "app_type": "resource_server",
  "oidc_conformant": true,
  "resource_server_identifier": "http://localhost:3001/",
  "token_exchange": {
    "allow_any_profile_of_type": ["on_behalf_of_token_exchange"]
  }
}' | jq -c '{client_id, client_secret}' > auth0-app-details.json
```

Notez les valeurs `client_id` et `client_secret` affichées dans la sortie; vous en aurez besoin pour configurer l'environnement de votre serveur MCP.

### Créer une API en aval

Créez l’API protégée que votre serveur MCP appellera au nom de l’utilisateur. Cette API correspond à votre API de logique métier (p. ex., une API de calendrier, une API de documents, etc.).

La commande suivante crée une API avec la configuration suivante :

* Autorisations client : accorde au serveur MCP un [accès délégué par l’utilisateur et un accès client](https://auth0.com/docs/get-started/applications/application-access-to-apis-client-grants.md) à l’API
* Application des permissions : exige des autorisations précises (`read:private`)
* Statut interne (première partie) : contourne le consentement de l’utilisateur pour vos propres applications

```shell theme={null}
auth0 api post resource-servers --data '{
  "identifier": "http://localhost:8787/",
  "name": "Protected Downstream API",
  "signing_alg": "RS256",
  "enforce_policies": true,
  "scopes": [
    {"value": "read:private", "description": "Private scope"}
  ],
  "subject_type_authorization": {
    "user": {
        "policy": "require_client_grant"
    },
    "client": {
        "policy": "require_client_grant"
    }
  },
  "skip_consent_for_verifiable_first_party_clients": false
}'
```

Notez l'identifiant de l'API (public) indiqué dans la sortie; vous le configurerez dans vos variables d'environnement sous le nom `API_AUTH0_AUDIENCE`.

> **Assign permissions to roles**
>
> After creating the downstream API and roles, assign the `read:private` permission to the roles.
>
> ```shell wrap lines theme={null}
> # Example for admin role
> auth0 roles permissions add YOUR_ADMIN_ROLE_ID --api-id "http://localhost:8787/" --permissions "read:private"
>
> # Example for user role
> auth0 roles permissions add YOUR_USER_ROLE_ID --api-id "http://localhost:8787/" --permissions "read:private"
> ```
>
> Replace `YOUR_ADMIN_ROLE_ID` and `YOUR_USER_ROLE_ID` with the role IDs you saved when creating the roles.

## Application d'exemple

**Javascript**

**Utiliser l'application d'exemple (recommandé)**

Commencez par télécharger l'application d'exemple de ce Démarrage rapide. L'exemple comprend un serveur MCP FastMCP intégré à Auth0 et une API protégée conçue avec
[Fastify](https://fastify.dev/).

Télécharger l’exemple de code auth-for-mcp fastmcp-mcp-on-behalf-of-tokenexchange-js

Une fois le téléchargement terminé, extrayez les fichiers et ouvrez le projet dans votre IDE préféré.

**Cloner le dépôt GitHub**

Clonez le dépôt et accédez au dossier de l'application d'exemple, qui comprend un serveur MCP FastMCP intégré à Auth0 et une API protégée conçue avec
[Fastify](https://fastify.dev/).

```shell wrap lines theme={null}
git clone https://github.com/auth0-samples/auth0-ai-samples.git
cd auth0-ai-samples/auth-for-mcp/fastmcp-mcp-on-behalf-of-tokenexchange-js
```

Une fois le dépôt cloné, ouvrez le projet dans votre IDE préféré.

L'application d'exemple illustre le flux OBO complet au moyen d'un outil `greet` qui :

1. Reçoit une requête authentifiée d'un client MCP
2. Échange le jeton contre un accès à l'API en aval
3. Appelle votre API protégée au nom de l'utilisateur
4. Renvoie le résultat

## Installer les paquets

Assurez-vous que [npm est installé](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). Ensuite, dans le répertoire `fastmcp-mcp-on-behalf-of-tokenexchange-js`, installez les paquets requis :

```shell theme={null}
npm install
```

## Créer votre fichier d'environnement

From the root of your sample app directory, run the following command to create a new `.env` file populated with all the required environment variables:

```shell wrap lines expandable theme={null}
CLIENT_ID=$(jq -r '.client_id' auth0-app-details.json) \
&& CLIENT_SECRET=$(jq -r '.client_secret' auth0-app-details.json) \
&& DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name') \
&& touch .env \
&& echo "AUTH0_DOMAIN=${DOMAIN}" > .env \
&& echo "AUTH0_AUDIENCE=http://localhost:3001/" >> .env \
&& echo "PORT=3001" >> .env \
&& echo "MCP_SERVER_URL=http://localhost:3001/" >> .env \
&& echo "MCP_AUTH0_CLIENT_ID=${CLIENT_ID}" >> .env \
&& echo "MCP_AUTH0_CLIENT_SECRET=${CLIENT_SECRET}" >> .env \
&& echo "MCP_AUTH0_EXCHANGE_SCOPE=read:private" >> .env \
&& echo "API_AUTH0_AUDIENCE=http://localhost:8787/" >> .env \
&& echo "API_BASE_URL=http://localhost:8787" >> .env \
&& rm auth0-app-details.json \
&& echo ".env file created with your Auth0 details:" \
&& cat .env
```

## Exécuter le serveur MCP et l'API

Run this command to start your server:

```shell theme={null}
npm run start
```

And in a separate window run this command to start the API:

```shell theme={null}
npm run start:api
```

## Échanger votre jeton d'accès

To call your APIs on a user's behalf, the MCP server uses the OBO token exchange to exchange the Auth0 access token it received from the MCP client (with the audience set to the MCP server itself) for a new Auth0 access token with the audience set to your API.

### Token exchange implementation

The MCP server exchanges tokens in two steps:

#### 1. Wrapper function: `bearerForUpstream()`

This function safely handles the token exchange process and error handling:

```javascript wrap lines highlight={5} theme={null}
async function bearerForUpstream(accessToken: string) {
  if (!accessToken) return { token: null, scopes: null };

  try {
    const result = await exchangeTokenOnBehalfOf(accessToken);
    return {
      token: result.accessToken,
      scopes: result.scope,
    }
  } catch (err) {
    console.error('Error during token exchange:', err);
    throw err;
  }
}
```

`bearerForUpstream()` calls `exchangeTokenOnBehalfOf()` and, upon a successful exchange, returns the new `accessToken` and its associated scope. If the exchange fails, it logs the error and re-throws it to be handled upstream.

#### 2. Exchange function: `exchangeTokenOnBehalfOf()`

This function, located in `src/auth0.ts`, calls Auth0's OBO token exchange endpoint using the SDK.

First, initialize the `ApiClient` with the credentials of the MCP server application:

```javascript wrap lines theme={null}
const apiClient = new ApiClient({
  domain: AUTH0_DOMAIN,
  audience: AUTH0_AUDIENCE,
  clientId: MCP_AUTH0_CLIENT_ID,
  clientSecret: MCP_AUTH0_CLIENT_SECRET,
});
```

Once you've configured the MCP server application, the `exchangeTokenOnBehalfOf()` function uses the client's `getTokenOnBehalfOf()` method to perform the token exchange.

`getTokenOnBehalfOf()` implements the OBO token exchange flow, which allows the MCP server to obtain a new token to call the downstream API while preserving the user's identity. It takes in the `accessToken`, `audience`, and `scope` parameters.

```javascript wrap lines theme={null}
export async function exchangeTokenOnBehalfOf(accessToken: string) {
    return await apiClient.getTokenOnBehalfOf(accessToken, {
      audience: API_AUTH0_AUDIENCE,
      ...(MCP_AUTH0_EXCHANGE_SCOPE && { scope: MCP_AUTH0_EXCHANGE_SCOPE }),
    });
}
```

**Python**

**Utiliser l'application d'exemple (recommandé)**

Commencez par télécharger l'application d'exemple de ce Démarrage rapide. L'exemple comprend un serveur MCP FastMCP intégré à Auth0 et une API protégée basée sur Starlette.

Télécharger l’exemple de code auth-for-mcp fastmcp-mcp-on-behalf-of-tokenexchange-python

Une fois le téléchargement terminé, extrayez les fichiers et ouvrez le projet dans votre IDE préféré.

**Cloner le dépôt GitHub**

Clonez le dépôt et accédez au dossier de l'application d'exemple, qui comprend un serveur MCP FastMCP intégré à Auth0 et une API protégée basée sur Starlette.

```shell wrap lines theme={null}
git clone https://github.com/auth0-samples/auth0-ai-samples.git
cd auth0-ai-samples/auth-for-mcp/fastmcp-mcp-on-behalf-of-tokenexchange-python
```

Une fois le dépôt cloné, ouvrez le projet dans votre IDE préféré.

L'application d'exemple illustre le flux OBO complet au moyen d'un outil `greet` qui :

1. Reçoit une requête authentifiée d'un client MCP
2. Échange le jeton contre un accès à l'API en aval
3. Appelle votre API protégée au nom de l'utilisateur
4. Renvoie le résultat

## Installer les paquets

Assurez-vous que [poetry est installé](https://python-poetry.org/docs/). Ensuite, dans le répertoire `fastmcp-mcp-on-behalf-of-tokenexchange-python`, installez les paquets requis :

```shell theme={null}
poetry install
```

## Créer votre fichier d'environnement

From the root of your sample app directory, run the following command to create a new `.env` file populated with all the required environment variables:

```shell wrap lines expandable theme={null}
CLIENT_ID=$(jq -r '.client_id' auth0-app-details.json) \
&& CLIENT_SECRET=$(jq -r '.client_secret' auth0-app-details.json) \
&& DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name') \
&& touch .env \
&& echo "AUTH0_DOMAIN=${DOMAIN}" > .env \
&& echo "AUTH0_AUDIENCE=http://localhost:3001/" >> .env \
&& echo "PORT=3001" >> .env \
&& echo "MCP_SERVER_URL=http://localhost:3001/" >> .env \
&& echo "MCP_AUTH0_CLIENT_ID=${CLIENT_ID}" >> .env \
&& echo "MCP_AUTH0_CLIENT_SECRET=${CLIENT_SECRET}" >> .env \
&& echo "MCP_AUTH0_EXCHANGE_SCOPE=read:private" >> .env \
&& echo "API_AUTH0_AUDIENCE=http://localhost:8787/" >> .env \
&& echo "API_BASE_URL=http://localhost:8787" >> .env \
&& rm auth0-app-details.json \
&& echo ".env file created with your Auth0 details:" \
&& cat .env
```

## Exécuter le serveur MCP et l'API

Run this command to start your server:

```shell theme={null}
poetry run python -m src.server
```

And in a separate window run this command to start the API:

```shell theme={null}
poetry run python -m src.api.server
```

## Échanger votre jeton d'accès

To call your APIs on a user's behalf, the MCP server uses the OBO token exchange to exchange the Auth0 access token it received from the MCP client (with the audience set to the MCP server itself) for a new Auth0 access token with the audience set to your API.

### How tools use token exchange

Here's how the `greet` tool performs the token exchange and calls the upstream API:

```python wrap lines highlight={10,11,12,13,14,17} theme={null}
@mcp.tool(name="greet")
@require_scopes(["tool:greet"])
async def greet(name: str, ctx: Context) -> str:
    user_name = name.strip() if name else "there"
    auth_info = ctx.request_context.request.state.auth
    user_id = auth_info.get("extra", {}).get("sub")

    logger.info(f"Greet tool invoked for user: {user_id}")

    # Exchange token and call upstream API
    exchange_result = await exchange_token_on_behalf_of(
        ctx.request_context.request.state.api_client,
        auth_info["token"]
    )

    async with httpx.AsyncClient() as client:
        response = await client.get(
            f"{config.api_base_url}/api/private-scope",
            headers={"authorization": f"Bearer {exchange_result['token']}"}
        )
        upstream_result = response.json()

    return f"Hello, {user_name} ({user_id})!\nUpstream API Response: {json.dumps(upstream_result, indent=2)}"
```

### The core logic: `exchange_token_on_behalf_of()`

The Python implementation uses the `exchange_token_on_behalf_of()` function that handles the token exchange:

```python wrap lines highlight={3,4,5,6} theme={null}
async def exchange_token_on_behalf_of(api_client, access_token: str) -> dict:
    """Exchange access token for downstream API token via On-Behalf-Of Token Exchange."""
    result = await api_client.get_token_on_behalf_of(
        access_token=access_token,
        audience=config.api_auth0_audience,
        scope=config.mcp_auth0_exchange_scope or None
    )
    return {"token": result["access_token"], "scopes": result.get("scope", "")}
```

`exchange_token_on_behalf_of()` uses the `get_token_on_behalf_of()` method of `ApiClient` from the `auth0-api-python` SDK. It takes in the `access_token`, `audience`, and optional `scope` parameters, and upon a successful exchange, returns the new access token and its associated scopes.

### Client configuration

The `ApiClient` is initialized in the `Auth0Middleware` (located in `src/auth0/middleware.py`) with the credentials of the MCP server application:

```python src/auth0/middleware.py wrap lines theme={null}
self.client = ApiClient(ApiClientOptions(
    domain=domain, # AUTH0_DOMAIN env var
    audience=audience, # AUTH0_AUDIENCE env var
    client_id=client_id, # MCP_AUTH0_CLIENT_ID env var
    client_secret=client_secret # MCP_AUTH0_CLIENT_SECRET env var
))
```

The configured client is then attached to the request context during middleware processing, making it available to all tools:

```python src/auth0/middleware.py wrap lines theme={null}
# In the Auth0Middleware dispatch method
request.state.api_client = self.client
```

## Testing your MCP server

Now that your MCP server is up and running, you can test it by using tools like [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector).

> **[Learn how to test your Auth0-powered MCP server](/ai/docs/mcp/guides/test-your-mcp-server-with-mcp-inspector.md)**

## Prochaines étapes

* Pour configurer l'autorisation de votre serveur MCP, suivez le guide de Démarrage rapide [Autorisation pour votre serveur MCP](/ai/docs/fr-ca/mcp/get-started/authorization-for-your-mcp-server.md).
