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

> [accordion] 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).

> [accordion] 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.

> [accordion] 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.

> [accordion] 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.
>
> > [tab] macOS
> >
> > brew install jq
>
> > [tab] Linux
> >
> > sudo apt-get install jq
>
> > [tab] Windows
> >
> > choco install jq

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

> [accordion] 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}'
> ```

> [accordion] 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.

> [accordion] 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) 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).

> [accordion] 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` に設定します。

> [accordion] 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.

## サンプルアプリ

> [tab] Javascript
>
> > [tab] サンプルアプリを使用する（推奨）
> >
> > まず、このクイックスタート用のサンプルアプリをダウンロードします。サンプルには、Auth0と統合されたFastMCP MCPサーバーと、
> > [Fastify](https://fastify.dev/)で構築された保護されたAPIが含まれています。
> >
> > auth-for-mcp fastmcp-mcp-on-behalf-of-tokenexchange-js のサンプルコードをダウンロード
> >
> > ダウンロードしたらファイルを展開し、お好みのIDEでプロジェクトを開きます。
>
> > [tab] 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 }),
>     });
> }
> ```

> [tab] Python
>
> > [tab] サンプルアプリを使用する（推奨）
> >
> > まず、このクイックスタート用のサンプルアプリをダウンロードします。サンプルには、Auth0と統合されたFastMCP MCPサーバーと、Starletteベースの保護されたAPIが含まれています。
> >
> > auth-for-mcp fastmcp-mcp-on-behalf-of-tokenexchange-python のサンプルコードをダウンロード
> >
> > ダウンロードしたらファイルを展開し、お好みのIDEでプロジェクトを開きます。
>
> > [tab] 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).

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

## 次のステップ

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