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

# ユーザーに代わってファーストパーティAPIを呼び出す

> MCPサーバーからAuth0で保護されたAPIを呼び出す方法について説明します。

Auth0はOn-Behalf-Of (OBO) token exchange ([RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html)) を実装しています。これにより、MCPサーバーはダウンストリームAPIを呼び出す際に、ユーザーのアイデンティティと権限を保持できます。OBO token exchangeのフローにおいて、MCPサーバーは2つの役割を担います。クライアントからリクエストを受け取るときはリソースサーバーとして、ユーザーに代わってダウンストリームAPIを呼び出すときはクライアントとして機能します。

ユーザーに代わってファーストパーティAPIを呼び出すには、MCPサーバーがMCPクライアントから受け取ったAuth0アクセストークンを、オーディエンスの異なる新しいアクセストークンと交換する必要があります。元のトークンのオーディエンスはMCPサーバーですが、新しいトークンのオーディエンスはダウンストリームAPIです。

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

このクイックスタートを終えると、次のものが完成します。

* OBO token exchangeを使用し、認証済みユーザーに代わって保護されたAPIを呼び出すMCPサーバー
* `@auth0/auth0-api-js`ライブラリ (JavaScript) または`auth0-api-python`ライブラリ (Python) によるトークンの検証と交換
* クライアントからMCPサーバー、そしてダウンストリームAPIに至るまで、エンドツーエンドのOBO token exchangeフローを実際に確認できる動作例

## 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

## テナント設定を構成する

> **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"
> ```

## Auth0アプリケーションとAPIをセットアップする

MCPサーバーは2つの役割を担うため、Auth0で2つの設定が必要です。

1. リソースサーバーとして：MCPクライアントから呼び出されるAPI
2. クライアントとして：トークンを交換してダウンストリームAPIを呼び出すアプリケーション

それでは、両方の設定を行いましょう。

### MCPサーバーを表すAPIを作成する

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.

### MCPサーバー用のアプリケーションを作成する

MCPサーバーがOBO token exchangeのクライアントとして動作できるよう、アプリケーションを作成します。このアプリケーションは、次の要件を満たす必要があります。

* MCPサーバーのAPIと同じ識別子 (`resource_server_identifier`) を持つこと
* `app_type: resource_server`を使用してMCPサーバーにリンクすること
* `token_exchange`設定でOBO token exchangeを有効にすること

次のコマンドを実行すると、MCPサーバーにリンクされ、OBO token exchangeが有効になったアプリケーションが作成されます。

```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
```

出力に表示される `client_id` と `client_secret` を控えておいてください。MCPサーバーの環境を設定する際に必要になります。

### ダウンストリームAPIを作成する

MCPサーバーがユーザーに代わって呼び出す、保護されたAPIを作成します。このAPIは、ビジネスロジックを担うAPI (カレンダーAPIやドキュメントAPIなど) に相当します。

次のコマンドを実行すると、以下の設定でAPIが作成されます。

* クライアントグラント：このAPIへの[ユーザー委任アクセスとクライアントアクセス](https://auth0.com/docs/get-started/applications/application-access-to-apis-client-grants.md)をMCPサーバーに付与します
* スコープの適用：特定の権限 (`read:private`) を必須とします
* ファーストパーティ扱い：自社のアプリケーションではユーザーの同意をスキップします

```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
}'
```

出力に表示される API 識別子 (オーディエンス) を控えておいてください。この値は後で環境変数 `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.

## サンプルアプリ

**Javascript**

**サンプルアプリを使用する（推奨）**

まず、このクイックスタート用のサンプルアプリをダウンロードします。サンプルには、Auth0と統合されたFastMCP MCPサーバーと、
[Fastify](https://fastify.dev/)で構築された保護されたAPIが含まれています。

auth-for-mcp fastmcp-mcp-on-behalf-of-tokenexchange-js のサンプルコードをダウンロード

ダウンロードしたらファイルを展開し、お好みのIDEでプロジェクトを開きます。

**GitHubリポジトリをクローンする**

リポジトリをクローンし、サンプルアプリのフォルダーに移動します。このフォルダーには、Auth0と統合されたFastMCP MCPサーバーと、
[Fastify](https://fastify.dev/)で構築された保護されたAPIが含まれています。

```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
```

クローンしたら、お好みのIDEでプロジェクトを開きます。

このサンプルアプリでは、`greet`ツールを使ってOBOフロー全体を実演します。このツールは次の処理を行います。

1. MCPクライアントから認証済みのリクエストを受け取る
2. トークンを交換して、ダウンストリームAPIへのアクセス権を取得する
3. ユーザーに代わって保護されたAPIを呼び出す
4. 結果を返す

## パッケージをインストールする

[npmがインストールされている](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)ことを確認してください。次に、`fastmcp-mcp-on-behalf-of-tokenexchange-js`ディレクトリで必要なパッケージをインストールします。

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

## 環境ファイルを作成する

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
```

## MCPサーバーと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
```

## アクセストークンを交換する

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**

**サンプルアプリを使用する（推奨）**

まず、このクイックスタート用のサンプルアプリをダウンロードします。サンプルには、Auth0と統合されたFastMCP MCPサーバーと、Starletteベースの保護されたAPIが含まれています。

auth-for-mcp fastmcp-mcp-on-behalf-of-tokenexchange-python のサンプルコードをダウンロード

ダウンロードしたらファイルを展開し、お好みのIDEでプロジェクトを開きます。

**GitHubリポジトリをクローンする**

リポジトリをクローンし、サンプルアプリのフォルダーに移動します。このフォルダーには、Auth0と統合されたFastMCP MCPサーバーと、Starletteベースの保護されたAPIが含まれています。

```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
```

クローンしたら、お好みのIDEでプロジェクトを開きます。

このサンプルアプリでは、`greet`ツールを使ってOBOフロー全体を実演します。このツールは次の処理を行います。

1. MCPクライアントから認証済みのリクエストを受け取る
2. トークンを交換して、ダウンストリームAPIへのアクセス権を取得する
3. ユーザーに代わって保護されたAPIを呼び出す
4. 結果を返す

## パッケージをインストールする

[poetryがインストールされている](https://python-poetry.org/docs/)ことを確認してください。次に、`fastmcp-mcp-on-behalf-of-tokenexchange-python`ディレクトリで必要なパッケージをインストールします。

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

## 環境ファイルを作成する

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
```

## MCPサーバーと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
```

## アクセストークンを交換する

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)**

## 次のステップ

* MCPサーバーの認可をセットアップするには、クイックスタート「[Authorization for Your MCP Server](/ai/docs/ja-jp/mcp/get-started/authorization-for-your-mcp-server.md)」を実施してください。
