CognitoとAgentCore GatewayでMCPサーバーにOAuth認証をつけよう
こんにちは! AWS でAI/ML Specialist SAをしている Kondo です。
本ブログは AWS AI Agent ブログ祭り(Zenn: #awsaiagentblogfes, X: #AWS_AI_AGENT_ブログ祭り)の第 10 日目です。
サマリー
- DCRなしのOAuth 3LO認証をリモートMCPサーバーに付与しました
- 構成は、MCPサーバーをAgentCore Gateway、認可サーバーをCognito、クライアントは自作コードです
- クライアントにClaude DesktopやVSCodeなどの既存のエージェント製品を使うと
失敗したのでだれかうまくいった人いたら教えて下さい。(追記: Amazon Quick Suiteからの接続には成功しました) - コードはすべてこちらで公開しています https://github.com/kondo-kj/mcp-with-oauth
動作イメージ
-
クライアントからリクエストする

-
ログイン画面がブラウザで表示される

-
ログインする

-
MCPが利用可能になる

MCPサーバーにOAuth認証をつけるとは
MCPサーバーというとstdio方式がまだ主流で、多くの人がローカルの中でMCPサーバーを利用しているかと思います。そんな中、リモートMCPサーバーも徐々に利用されてきています。
MCPの仕様では認可の方式が定められています。
stdio方式では環境からクレデンシャルを取得して利用することが推奨されており、リモートMCPサーバーではOAuthをベースとした方式が推奨されています。
stdio方式では長期のクレデンシャル情報を保存することが多いですが、リモートMCPサーバーの方式では短命なトークンを扱うため安全性が高いとされています。それ以外にもリモートMCPサーバーのほうが利用バージョンを統一できるなどのメリットもあります。
このあたりのMCPの認証認可の話はこちらの資料がわかりやすいのでおすすめです。
そんなこんなで、リモートMCPサーバーを立ててOAuth認証を付与するというのはニーズがあるわけです(これが言いたかっただけ)。
MCPの認可仕様
MCPの認可仕様についてざっくり確認していきましょう。私はセキュリティの専門家ではないため、正確ではない可能性がありますのでご承知おきください。AI/MLエンジニアの視点でのMCP認可仕様です。
本記事で参照するのは2025-06-18のSpecです。そろそろ新しくなりそうな気配も感じております。
これが認可フローです。ここでアレルギーが出てしまう人(私)もいると思いますが、ここをちゃんと確認するのが結局近道です。

フローの詳細を確認するにはこちらの記事がおすすめです
本記事では、ざっくりサマった内容と、各サーバーが持つべき役割にフォーカスしてお伝えします
1. 認可サーバー検出

最初はクライアントとMCPサーバーのやり取りです。このステップはこの後の認可に必要な情報を集めていると思っていただければいいと思います。
最終的にはこのような情報を得られます。認可サーバーとリソースサーバーの情報が得られました。スコープのような情報が含まれることもあります。
{
"authorization_servers": [
"https://cognito-idp.us-west-2.amazonaws.com/us-west-2_hogehoge"
],
"resource": "https://fugafuga.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp"
}
このステップからわかるMCPサーバーが持つべき役割
- トークンなしのリクエストが来たらWWW-AuthenticatedヘッダーにリソースメタデータURLを付与して返す
- Protected Resource Metadata(PRM)リクエストが来たらメタデータを返す
2. 認可サーバーのメタデータ検出

次は、クライアントと認可サーバーのやりとりです。先程のステップで認可サーバーのURLがわかっているので認可サーバーにリクエストができます。
リクエストの結果、認可サーバーメタデータとして次のようなjsonを取得します。
認可サーバーメタデータ
{
"authorization_endpoint": "https://fugafuga.auth.us-west-2.amazoncognito.com/oauth2/authorize",
"end_session_endpoint": "https://fugafuga.auth.us-west-2.amazoncognito.com/logout",
"id_token_signing_alg_values_supported": [
"RS256"
],
"issuer": "https://cognito-idp.us-west-2.amazonaws.com/hogehoge",
"jwks_uri": "https://cognito-idp.us-west-2.amazonaws.com/hogehoge/.well-known/jwks.json",
"response_types_supported": [
"code",
"token"
],
"revocation_endpoint": "https://fugafuga.auth.us-west-2.amazoncognito.com/oauth2/revoke",
"scopes_supported": [
"openid",
"email",
"phone",
"profile"
],
"subject_types_supported": [
"public"
],
"token_endpoint": "https://fugafuga.auth.us-west-2.amazoncognito.com/oauth2/token",
"token_endpoint_auth_methods_supported": [
"client_secret_basic",
"client_secret_post"
],
"userinfo_endpoint": "https://fugafuga.auth.us-west-2.amazoncognito.com/oauth2/userInfo"
}
このステップからわかる認可サーバーが持つべき役割
- 認可サーバーメタデータ検出(RFC8414)に対応している
Dynamic Client Registration(DCR)について
DCRはクライアント登録を事前にしなくて良くなる仕組み(雑)ですが、以下の理由により本記事ではDCRなしを前提とします
- MCPのSpecではSHOULDとなっており、MUSTではない
- セキュリティや運用面での課題が指摘されている
- 多くの認可サーバーのサービスで対応していない(Cognitoも)
- 今後新仕様で無くなる可能性がある
こちらについて、詳細は以下が詳しいです
※ただし、DCRなしを前提としたせいで発生する問題もありますので後述します
OAuth 2.1 3LO 認可フロー

ここは通常のOAuth2.1のAuthorization Code Grantの認可フローです。やや違うのはResource Indicator(RFC 8707)ですが、詳しくない方はそういうものがあると思ってください。
このステップからわかる認可サーバーが持つべき役割
- OAuth 2.1のAuthorization Code Grantの認可フローに対応していること(OAuth 2.0に対応していれば十分なこともあります)
- Resource Indicator(RFC 8707)に対応していること
このステップからわかるMCPサーバーが持つべき役割
- リクエストに付与されたアクセストークンを検証して認可を行う
各サーバーの役割を整理
MCPサーバーが持つべき役割
- トークンなしのリクエストが来たらWWW-AuthenticatedヘッダーにリソースメタデータURLを付与して返す
- Protected Resource Metadata(PRM)リクエストが来たらメタデータを返す
- リクエストに付与されたアクセストークンを検証して認可を行う
認可サーバーが持つべき役割
- 認可サーバーメタデータ検出(RFC8414)に対応している
- OAuth 2.1のAuthorization Code Grantの認可フローに対応していること(OAuth 2.0に対応していれば十分なこともあります)
- Resource Indicator(RFC 8707)に対応していること
これらの要件は、この役割をもったコードを書けば実現できるわけですが、めんどくさいですよね?なのでマネージドサービスでできたら嬉しいわけです。
MCPサーバーにAgentCore Gateway、認可サーバーにCognitoを用いることでこれらの要件を満たすことができることを本記事では示していきます。
クライアントは主にローカルのPythonコード(client.py)を用いて実験を行いますが、Claude CodeやClaude Desktop, VSCodeのようなエージェント製品もクライアントに用いた実験も軽く行います。
1. Cognitoの設定
まず最初にCognitoのセットアップをします。
⚠️ 注意: setup-cognito.py 内のユーザーID とパスワードを適宜変更してください。
uv run python setup-cognito.py
このスクリプトでは、次のことを実行します。
- ユーザープールの作成
- アプリクライアントの作成
- ユーザープールのドメインを作成し、マネージドログインの有効化
- テストユーザーの作成
- ログインURLの表示
ポイント
- ログイン画面の表示にはHosted UIとマネージドログインの2種類がありますが、RFC8707はマネージドログインしか対応していませんので、こちらを使います。ドメインの設定からマネージドログインを有効化しましょう。
2. AgentCore Gatewayの設定
AgentCore GatewayはMCPサーバーを構築するためのマネージドサービスです。AWS LambdaやOpenAPI SpecのAPIをMCPサーバー化することができます。また、どこか別の場所でホストされたリモートMCPサーバーの前段にGatewayを置くこともできて、トークン検証などを自分で実装する必要がなくなります。
README.mdに従って.envファイルで環境変数を設定してください。
uv run python create_gateway.py
ポイント
- 1で作成したCognitoのユーザープールをGatewayの認証設定で指定します
3. リソースサーバーの追加
RFC 8707に対応するために、CognitoのリソースサーバーにGatewayのエンドポイントを追加します。
README.mdに従って.envファイルで環境変数を設定してください。
uv run python add_resource_server.py
4. クライアントでの接続
クライアントでMCPサーバーに接続します
uv run python client.py
するとログイン画面が表示されるはずですので、設定したユーザー名とパスワードでログインしてください。ターミナルで >mcp が表示された接続完了です。listコマンドやcallコマンドでmcpを操作してみましょう。
client.pyは、https://github.com/modelcontextprotocol/python-sdk/tree/main/examples/clients/simple-auth-client を参考にカスタマイズしています。
内部では、MCD SDKの機能を使っています。気になる人は見てみてください。最も重要なコンポーネントはOAuthClientProviderです。
ステップbyステップでOAuthのフローを確認してみる
先程ざっくり確認したOAuthのフローをcurlでひとつずつリクエストして、挙動を見てみましょう
clinet.pyが中で行っている挙動を一個一個確認したい人は試してみてください
1. 認可サーバー検出
まずはトークンなしでリクエストします
curl -i -X POST $MCP_SERVER_URL \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":"ping","method":"tools/list"}'
↓
HTTP/2 401
www-authenticate: Bearer resource_metadata="https://sample-agentcore-gateway-hogehoge.gateway.bedrock-agentcore.us-west-2.amazonaws.com/.well-known/oauth-protected-resource"
x-amzn-remapped-content-type: application/json
仕様通りにwww-authenticateヘッダーにPRMのためのエンドポイントが返ってきました
次は、PRMリクエストです(RFC 9728)
curl -i https://sample-agentcore-gateway-hogehoge.gateway.bedrock-agentcore.us-west-2.amazonaws.com/.well-known/oauth-protected-resource
↓
{
"authorization_servers": [
"https://cognito-idp.us-west-2.amazonaws.com/us-west-2_fugafuga"
],
"resource": "https://sample-agentcore-gateway-hogehoge.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp"
}
PRMが返ってきました
2. 認可サーバーのメタデータ検出
次は認可サーバーに対してメタデータをリクエストします(RFC 8414)
curl -i https://cognito-idp.us-west-2.amazonaws.com/us-west-2_fugafuga/.well-known/openid-configuration
↓
認可サーバーのメタデータ
{
"authorization_endpoint": "https://hogehoge.auth.us-west-2.amazoncognito.com/oauth2/authorize",
"end_session_endpoint": "https://hogehoge.auth.us-west-2.amazoncognito.com/logout",
"id_token_signing_alg_values_supported": [
"RS256"
],
"issuer": "https://cognito-idp.us-west-2.amazonaws.com/us-west-2_fugafuga",
"jwks_uri": "https://cognito-idp.us-west-2.amazonaws.com/us-west-2_fugafuga/.well-known/jwks.json",
"response_types_supported": [
"code",
"token"
],
"revocation_endpoint": "https://hogehoge.auth.us-west-2.amazoncognito.com/oauth2/revoke",
"scopes_supported": [
"openid",
"email",
"phone",
"profile"
],
"subject_types_supported": [
"public"
],
"token_endpoint": "https://hogehoge.auth.us-west-2.amazoncognito.com/oauth2/token",
"token_endpoint_auth_methods_supported": [
"client_secret_basic",
"client_secret_post"
],
"userinfo_endpoint": "https://hogehoge.auth.us-west-2.amazoncognito.com/oauth2/userInfo"
}
3. OAuth 2.1 認可コードグラントフロー
得られた情報から認証URLを作成します
https://hogehoge.auth.us-west-2.amazoncognito.com/oauth2/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&scope=openid%20email%20profile&resource=https%3A%2F%2Fsample-agentcore-gateway-hogehoge.gateway.bedrock-agentcore.us-west-2.amazonaws.com%2Fmcp&state=YOUR_STATE_VALUE
ログインするとリダイレクトされて、そのURLに認可コードが含まれています。
認可コードを使って、Cognitoに対して、トークンをリクエストします
curl -X POST https://hogehoge.auth.us-west-2.amazoncognito.com/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=YOUR_AUTHORIZATION_CODE" \
-d "redirect_uri=YOUR_REDIRECT_URI" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "resource=https://sample-agentcore-gateway-hogehoge.gateway.bedrock-agentcore.us-west-2.amazonaws.com/mcp"
エージェント製品をクライアントにして試してみる
MCPサーバーを使うクライアントとして、最もよく使われるのは既存のエージェント製品です。例えば、Claude Code, Claude Desktop, VSCode, Amazon Q Developer等です。そちらでも検証してみましょう。ただし、これについてはあまりじっくり検証できていません(内部挙動が見えないのでトラブルシュートもうまくできない...)。
先に結論から書くと、うまくできたツールはありませんでした
(追記: Amazon Quick Suiteのみ接続に成功しました)
今回問題なのはDCRなしを前提としていることです。なぜなら上記のエージェント製品の多くはDCRありを前提としているものが多いからです。例えば下記のツールはすでに難しいことがWeb上で指摘されています。
- Claude Code: [BUG] Claude Code does not work with MCP servers that does not implement Dynamic Client Registration · Issue #3273 · anthropics/claude-code (https://github.com/anthropics/claude-code/issues/3273)
- Amazon Q Developer: Fallback to Client_id and secret flow if OAuth flow doesn't support Dynamic Client Registration (DCR) · Issue #2982 · aws/amazon-q-developer-cli (https://github.com/aws/amazon-q-developer-cli/issues/2982)
- Cline: MCP servers are not allowed to use oauth · Issue #4523 · cline/cline (https://github.com/cline/cline/issues/4523)
逆に下記のツールはDCRなしでもできる旨の記述が書かれていました
VS Code first starts with a Dynamic Client Registration (DCR) handshake and then falls back to a client-credentials workflow if the IdP does not support DCR. This gives more flexibility to the various IdPs to create static client IDs or specific client ID-secret pairs for each MCP server accordingly.
ただし、上記の記述からclient-credentials workflowしかサポートされていないと解釈することができます。実際、試してみたところ、ログイン画面がうまく表示されませんでした。
7月現在、ユーザーはDCRをサポートしていないサーバーを構成する際に、カスタムクライアントIDとクライアントシークレットを指定することもできます。
こちらはやってみたところ、生成されるログインURLがなぜかCognitoではなくMCPサーバー側のドメインを使っているという間違いが見られました。Claude Desktopのバグか私のミスか。
https://gateway-with-runtime-hogehoge.gateway.bedrock-agentcore.us-west-2.amazonaws.com/authorize?response_type=code&client_id=22zzzzzzzzzzzzzzz&redirect_uri=https%3A%2F%2Fclaude.ai%2Fapi%2Fmcp%2Fauth_callback&code_challenge=dxtp2ntCsF2kziQ7OcoI-uwkHQaW2nzyGMUu__QYJ1Y&code_challenge_method=S256&state=319Kn6QHs0esutZPrkjv9JQuInM6CLS5ZgHqFp1nGNg&scope=claudeai
ChatGPTでも試してみましたが、うまくいきませんでした
(追記)Amazon Quick Suiteをクライアントにした場合(唯一の成功例)
Amazon Quick Suiteはノーコードでエージェントを構築できるようなサービスですが、MCP Serverをコネクトできる機能があります。
こちらの機能を用いたところ、接続に成功しました。
-
インテグレーションの作成

-
認証設定

- Cognitoのアプリケーション側にリダイレクトURLを設定する

- Quick Suiteで接続したMCPを利用したチャットエージェントを作成する
まとめと今後の展望
MCPサーバーにOAuthを付与するという話はいろいろな人と会話する中で、よく話題に上がっていたため、今回その方法をまとめました。先述のようにDCRがあると現状いろいろな観点で難しいですが、DCRなしの議論があまりWeb上で見つからなかったため、今回思い切ってDCRなしの前提としました。
今後また仕様が変わったタイミングでいろいろと検証をしようと思います。
Discussion