MCP + OAuth2.1 + AWS Cognito Example について
このサンプルは、Node.js と Express.js を使い、OAuth 2.1 で MCP サーバーを保護する方法を示します。認可サーバーには AWS Cognito を使っていますが、実装はプロバイダーに依存しません。MCP の認可仕様を理解したい開発者向けです。
主な機能
- 01リソースサーバーとして動作する MCP サーバー
- 02PKCE を用いた OAuth 2.1 認可コードフロー
- 03保護されたリソースメタデータの検出
- 04動的クライアント登録(DCR)のサポート
- 05クライアント ID メタデータドキュメント(CIMD)のサポート
活用シーン
- 01MCP の認可の実装方法の学習
- 02MCP サーバーと AWS Cognito の接続
- 03DCR と CIMD によるクライアント登録方式の比較
MCP 対応
MCP サーバーに OAuth 認可を追加するサンプルで、/.well-known/oauth-protected-resource で PRM メタデータを公開し、リクエストごとにアクセストークンを検証します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
MCP + OAuth2.1 + AWS Cognito の例
概要
このリポジトリでは、Node.js と Express.js のみを使用して実装した OAuth 2.1 認可フローで、Model Context Protocol(MCP)サーバーを保護する方法を紹介します。この例では、認可サーバーとして AWS Cognito を使用していますが、実装はプロバイダーに依存せず、OAuth 2.1 に準拠する任意の認可サーバーで動作します。
MCP Authorization Specification(バージョン 2025-11-25)に基づき、このプロジェクトでは次の内容を紹介します。
- 汎用 OAuth エンドポイントを備えたリソースサーバー(RS)として動作する MCP サーバー
- プロバイダーに依存しない OAuth 2.1 の実装(例では AWS Cognito を使用)
- PKCE と RFC 8707 Resource Indicators を使用した OAuth 2.1 認可コードフロー
- Protected Resource Metadata(PRM)ドキュメントの検出
- 完全に動的な認可サーバーメタデータの検出
- Dynamic Client Registration(DCR)のサポート
- Client ID Metadata Documents(CIMD)のサポート
- MCP 2025-11-25 仕様に基づく強化されたセキュリティ機能
- 3 種類のクライアント実装:
- 認証情報を事前設定した静的クライアント
- 動的登録(DCR)を行う自動検出クライアント
- Client ID Metadata Documents(CIMD)を使用するメタデータクライアント
プロバイダーに依存しない設計
この実装は、OAuth 2.1 標準に準拠し、準拠する任意の認可サーバーとの互換性を確保します。
- MCP サーバー:標準 OAuth メタデータエンドポイントを公開し、バックエンドの認可サーバーにプロキシします
- クライアント:プロバイダー固有のロジックをハードコードせずに、認可サーバーを動的に検出します
- トークン検証:認可サーバーメタデータから検出した JWKS URI と発行者情報を使用します
- 柔軟なバックエンド:例として Cognito を使用していますが、任意の OAuth 2.1 サーバーに置き換えられます
新しい MCP 認可仕様を理解する
新しい MCP 認可仕様では、リソースサーバーと認可サーバーが明確に分離されているため、AWS Cognito、Okta、Auth0 などの既存の ID プロバイダーとの統合が容易になります。
仕様の主な要素は次のとおりです。
-
保護リソースメタデータ(PRM) ドキュメント
- MCP サーバーはこのドキュメントを
/.well-known/oauth-protected-resourceで提供します - 認可サーバー、サポート対象のスコープなどの情報が含まれます
- RFC9728(OAuth 2.0 Protected Resource Metadata)に準拠しています
- MCP サーバーはこのドキュメントを
-
ディスカバリープロセス
- クライアントが 401 Unauthorized レスポンスを受け取ると、WWW-Authenticate ヘッダーに PRM ドキュメントへの参照が含まれます
- クライアントは PRM ドキュメントを取得して、認可サーバーの URL を特定します
- クライアントは特定した URL から認可サーバーのメタデータを動的に取得します(エンドポイントのハードコードは不要です)
-
OAuth 2.1 認可
- PKCE を使用した認可コードフロー
- 認証済みリクエストでのベアラートークンの使用
- 特定した JWKS URI と発行者情報を使用した動的なトークン検証
-
クライアント登録の優先順位(MCP 2025-11-25)
- 事前登録済みのクライアント認証情報(サーバーで利用可能な場合)
- クライアント ID メタデータドキュメント(認可サーバーが
client_id_metadata_document_supported: trueを通知している場合) - 動的クライアント登録(RFC7591 によるフォールバック)
- 手動設定をユーザーに求めます(最後の手段)
-
動的クライアント登録(DCR)
- クライアントが新しい MCP サーバーに自動登録できるようにします
- 手動でクライアントを登録する手順が不要になります
- RFC7591(OAuth 2.0 Dynamic Client Registration Protocol)に準拠しています
-
クライアント ID メタデータドキュメント(CIMD)
- クライアントは OAuth メタデータを HTTPS URL で公開します
- URL 自体が
client_idになります - 認可サーバーはメタデータドキュメントを取得して検証します
- 事前登録やデータベースへの保存は不要です
- draft-ietf-oauth-client-id-metadata-document に準拠しています
この実装では、これらの概念を特定のプロバイダーに依存せずに適用する方法を紹介します。この例では、API Gateway エンドポイントと Lambda 関数を使用したカスタムの動的クライアント登録を AWS Cognito で実装していますが、基本的な OAuth フローは、準拠するあらゆる認可サーバーで動作します。
アーキテクチャ
Client → MCP Server → Authorization Server (e.g., AWS Cognito)
(Resource Server) (OAuth 2.1 Provider)
- クライアントがトークンなしでリクエストを送信します。
- MCP サーバーは、PRM メタデータを指す WWW-Authenticate ヘッダーとともに 401 Unauthorized を返します。
- クライアントは PRM を取得し、認可サーバーの URL を動的に特定します。
- クライアントは認可サーバーのメタデータを取得し、OAuth 2.1 認可コードフロー(PKCE を使用)を実行します。
- クライアントはアクセストークンを取得し、MCP サーバーへのリクエストを再試行します。
- MCP サーバーは、動的に特定した JWKS を使用してトークンを検証し、保護対象のリソースへのアクセスを許可します。
詳細については、アーキテクチャ概要を参照してください。
図:
動的クライアント登録(DCR)
この実装には OAuth 2.1 動的クライアント登録のサポートが含まれており、クライアントは次のことができます。
- MCP サーバーと認可エンドポイントを動的に検出する
- 認可サーバーに自身を登録する
- OAuth フロー用の認証情報を取得する
DCR フローは次のように動作します。
- クライアントが MCP サーバーの保護されたリソースメタデータを検出する
- クライアントが認可サーバー(Cognito)を検出する
- クライアントが API Gateway の DCR エンドポイントに登録する
- 登録によって Cognito アプリクライアントが作成され、認証情報が返される
- クライアントがこれらの認証情報を標準の OAuth 2.1 フローで使用する
実装に関する注記: AWS Cognito は、OAuth 2.0 DCR(RFC7591)で規定されている動的クライアント登録をネイティブではサポートしていません。この実装では、次の方法でこのギャップを補います。
- DCR API インターフェースを提供する API Gateway エンドポイント
- Cognito アプリクライアントをプログラムから作成する Lambda 関数
- 登録データを保存する DynamoDB
このアプローチにより、堅牢な認証と認可を実現する AWS Cognito を活用しながら、MCP 仕様の DCR 推奨事項への準拠を維持できます。
セキュリティに関する注記: この実装では、追加の認証を必要としない匿名 DCR を使用します。本番環境では、次の追加を検討してください。
- 登録リクエストのレート制限
- クライアント認証(mTLS、初期アクセストークン)
- 新規クライアントの承認ワークフロー
- 動的に登録されたクライアントのアクセススコープの制限
登録プロセスのセキュリティを強化するには、DCR セキュリティに関する推奨事項をご覧ください。
クライアント ID メタデータドキュメント(CIMD)
MCP Authorization Specification(2025-11-25)では、推奨されるクライアント登録方法として、クライアント ID メタデータドキュメントが導入されました。CIMD では、クライアントが HTTPS URL を client_id として使用できます。この URL には、クライアントの OAuth メタデータを記述した JSON ドキュメントが格納されます。
CIMD の仕組み
- クライアントが URL(例:
http://localhost:3003/client-metadata.json)でメタデータドキュメントを公開する - OAuth 認可の際、クライアントがこの URL を
client_idとして使用する - 認可サーバーが URL からメタデータドキュメントを取得する
- サーバーがドキュメントの構造とリダイレクト URI を検証する
- クライアントが標準の OAuth 2.1 フローを続行する
CIMD メタデータドキュメントの例
{
"client_id": "http://localhost:3003/client-metadata.json",
"redirect_uris": ["http://localhost:3003/callback"],
"client_name": "MCP CIMD Demo Client",
"grant_types": ["authorization_code"],
"response_types": ["code"],
"token_endpoint_auth_method": "none"
}
CIMD 認可プロキシ
AWS Cognito は DCR をネイティブではサポートしていないのと同様に、クライアント ID メタデータドキュメントもネイティブではサポートしていません。この実装では、MCP サーバーの認可プロキシを通じて CIMD を透過的に仲介します。
- MCP サーバーは、認可サーバーのメタデータで
client_id_metadata_document_supported: trueを通知する - MCP サーバーは、メタデータ内の
authorization_endpointとtoken_endpointを自身のエンドポイントに差し替える - クライアントが URL ベースの
client_idを提示した場合:- プロキシがクライアントのメタデータドキュメントを取得して検証する
- 既存の DCR インフラストラクチャを介して、Cognito アプリクライアントを透過的に作成する
- 対応付けられた認証情報を使って、リクエストを Cognito に転送する
- クライアントが標準の
client_id(事前登録済みまたは DCR)を提示した場合:リクエストは変更せずに Cognito へ渡される
metadata-client には CIMD 用のカスタムコードが一切ありません。仕様に準拠した標準的なクライアントと同様に、標準の OAuth エンドポイントでメタデータ URL を client_id として使用するだけです。仲介処理はすべてサーバー側で行われます。
CIMD のセキュリティ
認可プロキシには、次の機能が含まれています。
- SSRF 保護(プライベート IP アドレス範囲をブロックし、本番環境では HTTPS を必須とする)
- 厳格な
client_id検証(メタデータ URL と完全に一致する必要があります) - リダイレクト URI の検証
- レスポンスサイズ制限(64KB)とフェッチタイムアウト(5s)
- 重複したフェッチを防ぐインメモリキャッシュ
注: 開発環境では、http://localhost URL が許可されます。本番環境へのデプロイでは HTTPS を使用する必要があります。
クイックスタート
前提条件
- Node.js 18+ がインストールされていること
- 次のサービスにアクセスできる AWS テストアカウント
- 認可サーバー用の Cognito(ユーザープール 1 個、アプリクライアント 2 個)
- DCR と CIMD ブリッジ用の API Gateway/Lambda/DynamoDB(リソース 2 個、関数 2 個、テーブル 1 個)
- デプロイ用の CloudFormation(スタック 1 個)
- OAuth 2.1 フローの基本的な知識
セットアップ
-
リポジトリをクローンします
git clone https://github.com/empires-security/mcp-oauth2-aws-cognito.git cd mcp-oauth2-aws-cognito -
クライアントとサーバーの依存関係をインストールします
npm run install:all -
AWS リソースをデプロイします
npm run deploy -
次の場所にある生成された
.envファイルを確認しますsrc/client/.envsrc/auto-client/.envsrc/metadata-client/.envsrc/mcp-server/.env.env.exampleファイルと比較します- 必要に応じて CLIENT_SECRET を手動で確認/更新します
アプリケーションの実行
-
すべてのサービス(サーバー + 3 つのクライアント)を起動します
npm run dev -
http://localhost:3000 にアクセスして、事前登録済みクライアントの OAuth フローをテストします
-
新しいユーザーを登録します
- 「Log in」ボタンをクリックします
- Cognito のホストされた UI で「Sign up」を選択します
- 新しいユーザーアカウントを作成します
- メールで送信された確認コードを入力して、アカウントを確認します
- 確認が完了すると、アプリケーションにリダイレクトされます
-
「Fetch MCP Data」ボタンをクリックして、認証済みのリクエストを MCP サーバーに送信します
-
http://localhost:3002 にアクセスして、DCR フロー(Dynamic Client Registration を使用する自動検出クライアント)をテストします
-
http://localhost:3003 にアクセスして、CIMD フロー(Client ID Metadata Document クライアント)をテストします
クリーンアップ
- AWS リソースをクリーンアップします
npm run cleanup
詳しいセットアップ手順については、セットアップガイドを参照してください。
コントリビューション
コントリビューションを歓迎します。お気軽に Pull Request を送信してください。
- リポジトリをフォークします
- フィーチャーブランチを作成します(
git checkout -b feature/amazing-feature) - 変更をコミットします(
git commit -m 'Add some amazing feature') - ブランチにプッシュします(
git push origin feature/amazing-feature) - Pull Request を作成します
参考資料
- Model Context Protocol Authorization Specification (2025-11-25)
- OAuth 2.1 Draft
- OAuth 2.0 Protected Resource Metadata (RFC 9728)
- OAuth 2.0 Dynamic Client Registration Protocol (RFC 7591)
- OAuth Client ID Metadata Document (Draft)
- AWS Cognito Developer Guide
ライセンス
このプロジェクトは MIT License のもとでライセンスされています。詳細については LICENSE ファイルを参照してください。
著者
- Empires Security Labs 🚀
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。