MCPの認証はクライアントと代理対象のユーザーを特定します。認可は、アクセスできるツール、テナント、リソース、アクションを決めます。リモートHTTPサーバーについて、現在のMCP仕様はOAuth discovery、PKCE、resource indicator、bearer token、audience検証を使います。最終的なリソースは、引き続きバックエンドで認可する必要があります。
ローカルのstdioサーバーは、このHTTP認可フローではなくプロセス環境を使います。プロトコル上の対称性だけを理由に、リモートOAuth設計をstdioへコピーしないでください。
リモートMCP認可の役割
MCP認可仕様は3つの役割を定義します。
- MCPクライアントはOAuth clientとして動作する。
- MCPサーバーはprotected resource serverとして動作する。
- authorization serverはresource ownerを認証し、access tokenを発行する。
authorization serverは同じサービスの一部でも、独立したIDプラットフォームでも構いません。tokenを検証してアクセスを強制する責任は、引き続きMCPサーバーにあります。
discoveryはprotected resourceから始まる
クライアントが有効な認可なしで保護されたMCPサーバーを呼び出すと、サーバーはprotected resource metadataを示す401 headerとともにWWW-Authenticateを返します。このmetadataは、どのauthorization serverがこのリソース向けのtokenを発行できるかをクライアントへ伝えます。
次にクライアントはOAuth authorization server metadataを読み、authorization endpointとtoken endpointを見つけます。一般的なクライアントは初めて見るサーバーへ接続する可能性があるため、MCPはprotected resource metadataとauthorization server metadataを必要とします。
リクエストをMCPサーバーへ紐づける
クライアントはauthorization requestとtoken requestの両方にresourceパラメーターを含めます。この値は対象のMCPサーバーを識別します。MCPサーバーは、提示されたtokenが自身向けに発行されたことを確認する必要があります。
このaudience bindingにより、あるサービス向けのtokenを別サービスへ再送する攻撃を防ぎます。署名が有効でも、audienceが誤っていれば不十分です。
authorization codeを保護する
公開MCPクライアントはclient secretを安全に保持できません。仕様はProof Key for Code Exchange、つまりPKCEを必須とし、フローを開始したクライアントがauthorization codeを交換するときにverifierの所持を証明させます。
redirect URIは登録し、完全一致で照合します。クライアントはstate値を使って検証し、callbackを開始済みのリクエストへ紐づけます。localhostの開発用redirectを除き、HTTPSが必要です。
tokenはAuthorization headerだけで送る
保護されたすべてのHTTPリクエストでは次を送ります。
Authorization: Bearer <access-token>
MCP仕様はquery string内のaccess tokenを禁止しています。URLはheaderよりも、ブラウザー履歴、reverse proxyログ、analytics、screenshot、referrer dataへ漏れやすいためです。
不正または失効したtokenには401を返します。有効なIDでもscopeまたは権限が不足している場合は403を返します。
MCP tokenを下流へ渡さない
access tokenの対象はMCPサーバーです。第三者APIへ転送してはいけません。ツールが上流サービスを呼ぶ場合、MCPサーバーは別のOAuth clientとして動作するか、そのサービス向けの個別のバックエンド認証情報を取得します。
token passthroughはconfused deputy問題を引き起こし、audience境界を壊します。MCP APIキーガイドでは、上流の認証情報を置く場所を説明しています。
ユーザー、テナント、リソース、アクションを認可する
scopeは一つのレイヤーにすぎません。tokenを検証した後、現在のアプリケーション状態からアクセス権を計算します。
- どのユーザーまたはサービスIDを表しているか?
- どのテナントまたはorganizationがアクティブか?
- リクエストされたリソースはそのテナントの所有物か?
- このアクションはIDのroleに許可されているか?
- 現在の承認またはポリシー判断が必要なアクションか?
- 認証情報はまだ有効で、制限内にあるか?
下流APIでもリソース単位の認可を繰り返します。ツール名をread_invoiceにしても、宣言だけでAPI呼び出しが読み取り専用になるわけではありません。
影響の大きい承認を分ける
OAuth同意は、ある種類のアクセスを許可します。その後のすべての削除、購入、広範な変更に対する承認として扱うべきではありません。重大なアクションでは、呼び出し時に正確なリソースと効果を示します。
MCPツール仕様は、ツール呼び出しに関する明確なユーザー表示と確認を推奨しています。安全なインフラガイドでは、クラウド操作にplanとapplyの境界を追加しています。
失敗ケースをテストする
| テスト | 期待する結果 |
|---|---|
| bearer tokenなし | protected resource metadataの場所を含む401 |
| 失効したtoken | バックエンドを実行せず401 |
| 別のaudience向けtoken | ツールdispatch前に拒否 |
| 有効なtoken、scope不足 | 403 |
| 正しいscope、別テナントのリソース | 情報を開示せず拒否 |
| MCP tokenを上流APIへ提示 | 構造上不可能 |
| 変更されたredirect URI | 認可を拒否 |
| 破壊的リクエストのreplay | 効果は一つ、または承認が必要 |
ログ、error tracker、trace、analyticsにaccess tokenやrefresh tokenが含まれていないかも調べます。検証が正しくても、サーバーが認証情報を記録すれば意味がありません。
一つのtokenが止まる地点を追跡する
最初の未認証リクエストから、発行されたaccess tokenをMCPサーバーの検証地点まで追います。次に、別の上流認証情報を追跡します。同じtokenが両方の境界を越えていれば、ツールを追加する前に修正してください。
以下のプロンプトは、サーバーを呼び出すことなく、この追跡と不足しているテストを生成します。