MCP の OAuth 2.1 PKCE 対応ガイド
概要
OpenAI の Model Context Protocol (MCP) に対応するアプリケーションでは、認可フローに OAuth 2.1 の Authorization Code + PKCE を実装することが求められます。PKCE は公開クライアントでも安全に認可コードフローを利用するための仕組みで、MCP の「Deep Research」コネクタなどを動作させる上で必須となります。本記事では PKCE の基本的な流れと OAuth 2.0 との違い、/authorize・/token の各エンドポイントでの変更点を解説します。
PKCE が必須な理由
従来の認可コードフローではクライアントは固定の client_secret
を使って自身を認証します。しかしブラウザやモバイルアプリのような公開クライアントでは client_secret
を安全に保持できません。PKCE(Proof Key for Code Exchange)では以下の手順によってこの問題を解決します。
-
code_verifier の生成
クライアントは 43 文字以上のランダム文字列を生成しcode_verifier
として保持します。 -
code_challenge の生成
code_verifier
を SHA-256 でハッシュし Base64URL エンコードしたものをcode_challenge
とします。ハッシュ方式は常にS256
を使用します。 -
認可リクエストに code_challenge を送信
/authorize
にcode_challenge
とcode_challenge_method=S256
を含めてユーザー認証を行います。 -
トークンリクエストで code_verifier を送信
認可コードを受け取った後、/token
リクエストのボディにcode_verifier
をcode
と一緒に送ります。サーバーはcode_verifier
から計算したcode_challenge
が初回リクエストの値と一致するか検証します。 -
一致すればトークンを発行
code_challenge
が一致すれば正規のクライアントとしてアクセストークン(必要ならリフレッシュトークン)を返します。
この仕組みにより攻撃者が認可コードを盗んでも code_verifier
を知らなければ /token
でトークンを取得できません。
/authorize エンドポイントでの変更点
OAuth 2.1 では /authorize
リクエストで code_challenge
と code_challenge_method=S256
の送信が必須になります。例:
GET /authorize?client_id=CLIENT_ID&
response_type=code&
redirect_uri=CALLBACK_URL&
scope=read%20write&
state=STATE_VALUE&
code_challenge=BASE64URL(SHA256(code_verifier))&
code_challenge_method=S256
state
は CSRF 対策のためのランダム値で、リダイレクト時にそのまま返却する必要があります。OAuth 2.0 では code_challenge
と code_challenge_method
の送信は不要でした。
/token エンドポイントでのリクエスト
PKCE フローでは /token
へのリクエストに client_secret
を含めず、代わりに code_verifier
を送信します。
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
client_id=CLIENT_ID&
code=AUTHORIZATION_CODE&
redirect_uri=CALLBACK_URL&
code_verifier=ORIGINAL_CODE_VERIFIER
認可サーバーは code_verifier
から code_challenge
を再計算して検証します。リクエストヘッダに Basic 認証を付ける必要もありません。
OAuth 2.0 との主な違い
変更点 | OAuth 2.0 | OAuth 2.1 |
---|---|---|
PKCE | 公開クライアント向けに推奨で必須ではない | すべてのクライアントで必須。code_verifier と code_challenge を必ず利用 |
Implicit フロー | SPAs 向けに存在しアクセストークンを直接返す | 廃止。SPAs も認可コード+PKCEを利用する |
Resource Owner Password Grant | ユーザーの ID・パスワードを直接送信してトークン取得が可能 | 廃止。代わりに認可コード+PKCEを使用 |
リダイレクトURIの一致 | ワイルドカードなど柔軟な一致が可能 | 完全一致が必須。登録済みURIと完全一致しない場合は拒否 |
トークンの送信方法 | クエリ文字列に含めることも許可 | クエリ文字列での送信は禁止。Authorization: Bearer ヘッダ等で送る |
今後の実装ポイント
- MCP 対応アプリケーションでは
/.well-known/oauth-authorization-server
と/.well-known/oauth-protected-resource
にメタデータを公開し、grant_types_supported
にauthorization_code
(必要ならclient_credentials
)を含める。 -
tools_offered
には MCP の規定に沿って必要なツールのみ(search
やfetch
など)を列挙する。 - 認証されていないアクセスには
401
とWWW-Authenticate
ヘッダを返し、resource_metadata
に/.well-known/oauth-protected-resource
の URL を示す。 -
/token
エンドポイントではclient_secret
の代わりにcode_verifier
を検証し、アクセストークンを発行する。
まとめ
OAuth 2.1 ではすべてのクライアントで PKCE が必須となり、OpenAI MCP のような公開クライアントでも安全に認可コードフローを利用できるようになっています。/authorize
で code_challenge
を送信し、/token
で code_verifier
を検証するフローを正しく実装することで、MCP コネクタの安全な動作を実現できます。
Discussion