メインコンテンツまでスキップ

MCPサーバーのセキュリティ: OAuth、オーディエンス・バインディング、混乱した代理

上級
What you'll learn
  • リモート(HTTP)MCPサーバーが単なるAPIキーのエンドポイントではなく、OAuth 2.1のリソースサーバーである理由を理解する
  • ディスカバリのハンドシェイクをたどる: 401 → 保護されたリソースのメタデータ → 認可サーバーのメタデータ → トークン
  • トークンのオーディエンス・バインディング(RFC 8707)と、それがあるサービスのトークンを別のサービスで機能させない理由を説明する
  • 混乱した代理の罠と、それを塞ぐ唯一のルール、すなわちクライアントのトークンを上流APIへ決してパススルーしないことを挙げる
  • MCPサーバーをインターネットに公開する前に、短いハードニング・チェックリストを適用する

MCPは目新しいものからエージェントがツールに到達する既定の手段へと変わりました。つまりMCPサーバーは今や本物のデータと本物のアクションの前に立っています。STDIOで起動するローカルサーバーはその環境を信頼します。環境変数から資格情報を読み取り、防御すべきネットワーク境界がありません。同じサーバーをリモート(HTTP)にした瞬間、URLに到達できる者は誰でもそれを呼び出そうとできます。これはそれを認可の問題へと反転させ、MCP仕様は独自のAPIキー方式ではなくOAuth 2.1でそれに答えます。

このページはリモートのケースについてです。サーバーがSTDIO専用であれば、仕様はOAuthフローに従わないことを明示しています。環境から資格情報を取得して先に進んでください。

3つの役割

OAuthは問題を3者に分割します。MCPはそれらにきれいに対応します:

MCPのOAuthフローにおける登場人物
Enter キーまたはスペースキーでカードを裏返します。左右の矢印キーでカードを移動できます。用語を表示しました。
1 / 3

重要な考え方の転換: MCPサーバーはログインそのものを決して扱いません。 それは他者が発行したトークンを検証するだけです。この分離こそが、あなたが書いたサーバーの前に既製のアイデンティティプロバイダーを置けるようにするものです。

ディスカバリのハンドシェイク

クライアントは、どこで認証するかをあらかじめ設定しておく必要があってはなりません。MCPはディスカバリを自動化し、401によって駆動します:

Guided walkthrough1 of 6
  1. 最初のリクエストは裸で送られます。サーバーはHTTP 401 Unauthorizedと、そのリソースメタデータURLを指すWWW-Authenticateヘッダーでそれを拒否します。

クライアント側にハードコードされた認証設定がないことに注目してください。401がすべてをブートストラップします。それこそが要点です。エージェントは一度も見たことのないサーバーに接続し、どう認証するかを見つけ出せるのです。

オーディエンス・バインディング: 荷重を支えるルール

オーディエンス・バインディングが防ぐために存在する障害モードがこれです。あるユーザーがcalendar.example.com向けに発行されたトークンを持っているとします。evil.example.comにある悪意ある(あるいは単にずさんな)MCPサーバーが、クライアントを騙してそのトークンを自分に送らせます。もしevilがそれを受け入れれば、それはユーザーとしてカレンダーAPIを呼び出せるようになります。あるサービスのトークンが別のサービスで機能してしまいました。OAuthのセキュリティ境界が今まさに崩壊したのです。

その対策が**リソースインジケーター(RFC 8707)**です:

Guided walkthrough1 of 3
  1. 認可リクエストとトークンリクエストの両方で、クライアントは呼び出そうとしているMCPサーバーの正規URIに設定したresourceパラメータを含めなければなりません(MUST)。例: resource=https://mcp.example.com。ASがそれをサポートしているか不確かでも、これを送ります。

認可リクエスト上のresourceパラメータ(URLエンコード)

&resource=https%3A%2F%2Fmcp.example.com

正規URIは厳格です。https://mcp.example.comhttps://mcp.example.com:8443/mcpは有効です。mcp.example.com(スキームなし)とhttps://mcp.example.com#frag(フラグメント)は無効です。相互運用性のため、末尾スラッシュのない形式を優先してください。

混乱した代理: トークンを決してパススルーしない

これは、善意のMCPサーバーを攻撃者のプロキシに変えてしまう間違いです。これはエージェントセキュリティにおける同じ混乱した代理の問題を、1つの具体的なルールに研ぎ澄ましたものです。

MCPサーバーはしばしば上流API(GitHub、データベースサービス、別のSaaS)を呼び出す必要があります。誘惑は、クライアントが渡してきたトークンを取り、それを上流へ転送することです。やめてください。 仕様は率直です。MCPサーバーはクライアントから受け取ったトークンをパススルーしてはなりません(MUST NOT)。

なぜ危険か: クライアントのトークンはあなたのサーバーをオーディエンスとして発行されました。もしあなたがそれを転送すれば、上流APIはそれをあなたから来たかのように信頼したり、あなたがすでに検証したと想定したりするかもしれません。そして今や1ホップ用にスコープされたトークンが、誰の同意モデルの外でも、2ホップ先で作業をしているのです。

Watch out
  • あなたのMCPサーバーが上流APIを呼び出す場合、それはそのAPIに対する別個のOAuthクライアントとして振る舞い、上流の認可サーバーから自分自身のトークンを取得します。2つの独立したトークン、2つの独立したオーディエンス。クライアントのトークンはあなたの玄関で止まります。

事前のハードニング・チェックリスト

リモートMCPサーバーが公共のインターネットに触れる前に:

Guided walkthrough1 of 7
  1. すべてのASエンドポイントはHTTPSでなければなりません(MUST)。リダイレクトURIはHTTPSまたはlocalhostでなければなりません(MUST)。それ以外は不可です。

理解度チェック

理解度チェック

0/4
  1. リモートMCPサーバーがアクセストークンなしのリクエストを受け取ります。仕様はまず何をすることを求めていますか?
  2. トークンのオーディエンス・バインディング(RFC 8707)は何を防いでいますか?
  3. あなたのMCPサーバーが上流のGitHub APIを呼び出す必要があります。クライアントが送ってきたアクセストークンをどうすべきですか?
  4. STDIO(ローカル)MCPサーバーについて、仕様は資格情報をどう扱うべきだと言っていますか?

出典とさらなる読み物