🍖

MCPのOAuth認証で仕様通りに作るのが難しいこと3選

に公開

Qiita Advent Calendar 2025「Model Context Protocol(MCP) Advent Calendar 2025」16日目の記事です。

https://qiita.com/advent-calendar/2025/mcp

はじめに

MCPは2024年の年末に公開されて、2025年に一気に広がった2025年を代表する技術といえます。
MCPサーバーを使うことで、生成AIは外部のデータソースやツールに安全かつ標準化された方法でアクセスできるようになりました。

2025年の短期間の間に、MCPサーバーはエンジニアを中心とした生成AI活用に積極的な層に一気に広がりました。しかし、それ以上の広がりにはいくつかの壁に直面しています。

例えば、技術的な導入障壁の高さ 。MCPサーバーを自力で設定するには、CLIの知識やJSON形式の設定ファイルの編集が必要で、非エンジニアには敷居が高いものがあります。
また、ユースケースの不明確さ も問題です。「MCPで何ができるか」は理解できても「自分の業務でどう活用すべきか」が見えない人が多いです。エンジニアにとってはコーディングへの活用という分かりやすい活用方法がありますが、営業やマーケティング、バックオフィス業務でどう使えば効果的なのか、具体的な成功事例がまだ少ない状況です。

それらを解決するためにMCPサーバーを組み込んだ製品をサービスとして提供することが考えられます。しかしその場合、最大の壁とも言える 認証とセキュリティの複雑さ に直面します。
エンジニアが個人のPC内で完結して使う場合は、認証や認可はシンプルで特に大きな問題はありません。しかし、大勢が使うサーバー上でMCPを使用する場合、極めて複雑で分かりにくい認証フローが必要になります。

MCPの仕様ではOAuthによる認証方式が定められています。

https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization

なので、これに従えば良いと考えるかもしれません。しかし、MCPはここ1年で登場した新しい仕様です。OAuthプロバイダー側がMCPが求める認証に対応していないという外的要因により、仕様通りに実装できないという問題に直面します。

この記事では、私が実際に直面した素直にやると仕様通りに実装できなかったMCPの認証仕様について、3点ほど説明したいと思います。

  • DCR (動的クライアント登録) : RFC 7591
  • resourcesパラメータ : RFC 8707
  • PKCE : RFC 7636

DCR (動的クライアント登録) : RFC 7591

DCRとは

一般的なOAuth対応は、利用する環境やアプリごとにクライアントIDとクライアントSecretを発行します。そうすることで、特定のアプリや利用者のみにサービスを提供しています。
しかし、MCPでの利用となると事情が異なります。ユーザーが自由にインストールできるMCPサーバーに対して、都度クライアントIDとSecretを取得するというのはハードルが高いと考えられます。
そこで、MCPの仕様では、アプリケーションが自動的にクライアント登録をするDCR(動的クライアント登録)を採用しています。DCRがあれば、ユーザーは技術的な設定なしでMCPサーバーを使い始めることが出来ます。

実態

と、ここまでMCP側の都合を書きましたが、サービスの提供側からすれば知らない人が好き勝手にOAuthに登録してくるDCRはリスクでしかありません。また、2025年時点では、実質的にDCRはMCP以外での活用は聞いたことがありません。
そんな中でDCRに積極的に対応するOAuthプロバイダーはほぼ存在しないですし、今後も極一部のサービスにとどまるでしょう。

対処方法

いくら仕様に定められていても、OAuthプロバイダー側の対応が見込めないのであれば、DCR前提で考えることはできません。考えられる対応は2択です。

  1. MCPクライアントで、クライアントIDとクライアントSecretを登録する
  2. MCPサーバーなどのサーバーサイドでDCRの仕様を吸収する

1に関しては、面倒くさいけどDCRをあきらめて都度登録しましょうということですね。MCPの本家であるClaudeですらクライアントIDとクライアントSecretを登録する機能がついているので、実用的なMCPクライアントには必須機能になっているのが実態です。
ただし、MCPクライアントでOAuthのクライアントIDやクライアントSecretを持つ場合は取扱に最大限の注意が必要ですし、この後で述べるPKCE対応の重要度も上がります。セキュリティ要件と仕組みを十分に検討するようにしてください。

2に関しては、クライアントではなくサーバー側にOAuthのProxyを組み込むことで、DCRの仕様を吸収する方針になります。そうすることで、クライアント側は完全にMCPの仕様通りに実装ができます。
こちらに関しては、FastMCPというライブラリではOIDC Proxyという機能が提供されており、これを活用することで比較的簡単にDCRの仕様を吸収したMCPサーバーを実装できます。OAuth認証付きのMCPサーバーの実装を検討している場合は、試してみても良いかと思います。
過去の私のこちらの記事でも紹介していますので、実際の使い方に興味があれば参考にしてみてください。
https://zenn.dev/ncdc/articles/2d704a34ca1eed

resourcesパラメータへの対応 : RFC 8707

resourcesパラメータとは?

OAuth 2.0では、scopeパラメータを使ってアクセス権限の範囲を指定します。しかし、scopeだけでは「どのリソースサーバーに対する権限か」を明示できません。
RFC 8707で定義されたresourcesパラメータは、アクセストークンが有効なリソースサーバーを明示的に指定するための仕組みです。

GET /authorize?
  client_id=xxx&
  scope=read write&
  resource=https://api.example.com&  ← これ
  ...

MCPでは、複数のMCPサーバーが異なるリソースにアクセスする可能性があるため、resourcesパラメータによる明示的なリソース指定が仕様に含まれています。これにより、各MCPサーバーが必要なリソースにのみアクセスできるよう、より細かい権限管理が可能になります。

実態

resourcesパラメータの問題は、MicrosoftのEntraID(旧AzureAD)をプロバイダーとするMCPサーバーを作った時に遭遇しました。
AzureADはかつて独自のresourceパラメータを持っていました。現在は使用されていない仕様ですが、この時の影響でRFC 8707で定義されたresourcesパラメータを渡すと明示的にエラーになってしまいました。

また、他の主要なOAuthプロバイダーでもresourcesパラメータに対応していないのが現状です。
代わりにaudienceパラメータを使用するプロバイダーや、scope内にリソース識別子を埋め込む方式を採用しているプロバイダーもあり、現実には標準化されていません。
EntraID以外の多くのOAuthプロバイダーはRFC 8707に対応してなくてもresourcesパラメータが無視されるだけで見た目は正常に動作することが多いので実害は少ないのですが、厳密には仕様は満たせていないことも良くあります。
一見正常に動いている場合でも、各プロバイダーの仕様を確認してセキュリティが担保されているかを検証することをお勧めします。

対処方法

今回エラーになったのはEntraIDの認証を、前述のOIDC Proxy(FastMCP)を使ってMCPサーバーに実装した時に発生しました。
OIDC Proxyは、自動でresourcesパラメータを埋め込んでしまいます。このため該当処理をOverrideしてresourcesパラメータを削除する処理を実装しました。具体的にはこんな感じです。
https://github.com/ncdcdev/sharepoint-docs-mcp/blob/v0.4.0/src/server.py#L87-L118

PKCE対応 : OAuth 2.1 / RFC 7636

PKCEとは?

PKCE (Proof Key for Code Exchange) は、OAuth 2.0の認可コードフローにおけるセキュリティ攻撃を防ぐための拡張仕様です。
通常の認可コードフローでは、認可コードが傍受された場合、攻撃者がそのコードを使ってアクセストークンを取得できてしまう可能性があります。特にネイティブアプリやSPAでは、クライアントsecretを安全に保存できないため、この脆弱性が深刻です。

PKCEは、以下の仕組みでこの問題を解決します。

  1. クライアントが code_verifier(ランダムな文字列)を生成
  2. code_verifier をハッシュ化した code_challenge を認可リクエストに含める
  3. トークンリクエスト時に元の code_verifier を送信
  4. サーバーが code_verifiercode_challenge の整合性を検証

これにより、認可コードだけを傍受しても、元のcode_verifierがなければトークンを取得できません。OAuth 2.1では、PKCEがすべてのクライアントで必須とされており、MCP仕様でもPKCEの使用が求められています。

実態

PKCEが引っかかったのは、Boxです。ユーザーフォーラムにも要望がでていますが、BoxはPKCEに対応していません。
https://pulse.box.com/forums/909778-help-shape-the-future-of-box/suggestions/50572956-add-pkce-support-for-oauth2-applications

Boxのように、PKCE非対応のプロバイダーは2025年時点でも存在します。特に古いOAuth実装を持つサービスでは、PKCEへの対応が後回しにされているケースがあります。

対処方法

OAuthプロバイダーが対応していない以上、どうしようもありません。PKCE非対応の場合、従来通りclient_secretを使った認可コードフローに頼るしかありません。
一方で、PKCE対応のOAuthプロバイダーが相手の場合は当然PKCE対応するべきですので、MCPサーバーを活用したサービスでは両方の実装をして切り替える必要になります。

また、前述の通りPKCE対応しない場合はネイティブアプリやSPAでは、セキュリティ上の問題が特に大きくなります。これに対しては、DCRの対策でも上げたサーバー側でOAuthを仕様を吸収する方式を取れば、実装の手間と引き換えにセキュリティリスクの軽減が可能です。

まとめ

この記事では、MCP仕様が求めるOAuth認証と、実際に実装したときの発生したOAuthプロバイダーの挙動との間に存在する3つのギャップを紹介しました。

  • DCR (RFC 7591)
    • 仕様では想定されているが、対応プロバイダーがほぼ存在しない
  • resourcesパラメータ (RFC 8707)
    • 実態として標準化されてなく、プロバイダーによってはエラーになる
  • PKCE (RFC 7636)
    • OAuth 2.1では必須化されているが、未対応のプロバイダーが残存

MCPの認証仕様は理論的には美しく設計されていますが、現実のOAuthプロバイダーの実装との乖離により、仕様通りの実装は極めて困難です。
MCPを活用したサービスの開発には、接続先のOAuthプロバイダー毎の仕様を確認して、それらに対応した柔軟な実装をしつつ、セキュリティを担保する事が必要です。

補足:マネージドサービスの活用について

これらの課題に対するアプローチとして、マネージドサービスの活用も選択肢になります。例えば、Amazon Bedrock AgentCore Gatewayは、MCPのOAuth認証の複雑さを抽象化し、PKCE対応や認証プロキシの実装も提供しています。

https://aws.amazon.com/jp/blogs/news/transform-your-mcp-architecture-unite-mcp-servers-through-agentcore-gateway/

柔軟性の低下やベンダーロックされるというトレードオフはありますが、以下のような場合には有力な選択肢となります。

  • 迅速なプロトタイピングや市場投入を優先する場合
  • インフラ管理のオーバーヘッドを削減したい場合
  • AWS以外での動作や移行を考える必要がない場合

このようなマネージドサービスをどこまで活用するかは、チームの技術スタック、運用体制、長期的な戦略によって判断しましょう。

NCDC テックブログ

Discussion