MCPを社内プロジェクトに組み込んだ翌週、上司から一言がきた——「このAPIエンドポイント、認証なしで外から叩けるけど大丈夫?」。OAuthの設定を「あとでやる」と先送りにし続けた開発担当者が実際に経験するヒヤリ体験を軸に、この記事では初心者・企業担当者がMCP×OAuth設定でつまずく落とし穴と、今日中に動く実務設定手順をまとめた。2026年6月18日にMCPプロトコルの仕様が更新され、OAuth Resource Serverの正式分類とセキュリティベストプラクティスセクションが追加されたいま(出典:MCP公式ブログ)、設定を後回しにするリスクは以前より高くなっている。
図解
OAuth認証フロー(MCPクライアント → 認可サーバー → MCPサーバー → ツール実行)
flowchart LR
A["MCPクライアント\nClaude / エージェント"] -->|①認証リクエスト| B["認可サーバー\n社内IdP / Auth0 等"]
B -->|②アクセストークン発行| A
A -->|③トークン付きリクエスト| C["MCPサーバー\nリソースサーバー"]
C -->|④トークン検証| B
B -->|⑤検証OK| C
C -->|⑥ツール実行| D["ツール\nファイル・DB・API 等"]
D -->|⑦結果返却| A
「あとでやれば十分」——その先延ばしが呼んだヒヤリ
MCP(Model Context Protocol)を社内ツールに組み込んだ最初の数日は、とにかく動けばいいという雰囲気になりがちだ。PoC(概念実証)では認証なしのシンプル構成が一番手っ取り早い。Claudeがファイルを読んでくれた、DBから情報を取ってきてくれた——そのこと自体がうれしくて、セキュリティ設定は後回しになる。
問題は「その構成のまま本番に上がる」ことが思いのほか多い点だ。
典型的な流れはこうだ。
- 社内Slackで好評を得た
- 「もう少し安定したら設定しよう」と先延ばした
- 気づいたら複数部署に展開されていた
- 外部向けプロジェクトのエンドポイントと同居していた
この状況で上司や外部のセキュリティ担当から「そのエンドポイント、誰でも叩けるよね?」と指摘されると、手が止まる。
なぜ認証なしが危ないのか——MCPのリスク構造を押さえる
MCPサーバーはAIエージェントにツール(ファイル操作・DB参照・外部API呼び出しなど)を使わせる「橋」だ。この橋の入口に鍵がかかっていなければ、橋を渡れるのはAIエージェントだけではない。
認証なし(またはAPIキー一枚)の構成が本番環境で抱えるリスクは大きく3つある。
リスク① 未認証エンドポイントへの外部アクセス
MCPサーバーをローカルで動かしている間は問題が見えにくい。しかし社内展開・クラウドデプロイの段階でエンドポイントが外部に露出するケースがある。認証がなければ、URLを知っている第三者がツールを呼び出せてしまう。
リスク② APIキー漏洩のダメージが全権限に及ぶ
1枚のAPIキーで「全ツール・全権限」を束ねている構成では、そのキーが漏れた瞬間にすべてのツールが操作可能になる。ログにキーを出力してしまった、GitHubにうっかりコミットしてしまった——こうした事故は初心者だけでなく経験者でも起きる。
リスク③ 誰が何を実行したか追跡できない
監査ログのない構成では「あの日誰がDBを操作したのか」を後から確認できない。セキュリティインシデントが起きたとき、原因究明が不可能になる。
APIキー認証とOAuth 2.1——初心者が混同しやすい「違い」を整理する
初心者が最もよく抱く誤解が「APIキーがあれば十分ではないか」という考えだ。個人開発やPoC段階ではAPIキー認証も現実的な選択肢になるが、複数人・複数システムが使う本番環境ではOAuth 2.1が必要になる理由がある。
| 比較項目 | APIキー認証 | OAuth 2.1 |
|---|---|---|
| セキュリティ水準 | 低〜中 | 高 |
| 設定コスト | 低 | 中〜高 |
| トークン有効期限 | なし(手動ローテーション) | あり(自動更新可) |
| 権限の細かい制御 | 困難(全権限か無権限) | スコープで細かく設定可 |
| 漏洩時の被害範囲 | 全権限 | トークン期限内の限定スコープ |
| 監査・トレース | 難しい | IdPログで追跡可能 |
| 推奨場面 | 個人開発・PoC | 企業・本番運用 |
MCPにおけるポイントは「MCPサーバーがOAuthのリソースサーバーになる」という構造だ。
OAuth 2.1では役割が3つに分かれる。
- クライアント:MCPを呼び出すアプリ・Claudeエージェント
- 認可サーバー:社内IdP、Auth0、Microsoft Entraなど——トークンを発行する側
- リソースサーバー:MCPサーバー——トークンを受け取って検証する側
MCPサーバーは「トークンを受け取って検証する側」に立つ。MCP公式ブログによると、2026年6月18日の仕様更新でこのOAuth Resource Serverとしての分類が正式に導入され、あわせてリソースインジケーターによるトークンの使い回し防止も仕様化されたとのことだ(出典:MCP公式ブログ)。
30分で動かすOAuth設定——実務手順
ステップ1:認可サーバーを決める
まず「どのIdPをOAuthの認可サーバーにするか」を決める。
- すでに社内にIdPがある場合(Microsoft Entra / Okta / Google Workspace):そこにOAuthクライアントを登録するだけで済む。新たなサービスを立てる必要はない。
- 社内IdPがない場合:Auth0・Keycloak(OSS)・Amazon Cognitoのいずれかが現実的だ。Auth0については無料プランの上限や詳細をAuth0公式で確認してほしい。
ステップ2:MCPサーバーにトークン検証を追加する
MCPサーバー(Node.js / Pythonが多い)にミドルウェアを追加し、受け取ったアクセストークンを認可サーバーで検証する処理を入れる。
Node.js(Express)の最小構成例:
const { auth } = require('express-oauth2-jwt-bearer');
const checkJwt = auth({
audience: 'https://your-mcp-server.example.com', // MCPサーバーのAPI識別子
issuerBaseURL: 'https://your-idp.example.com/', // 認可サーバーのURL
});
app.use('/tools', checkJwt); // ツールエンドポイントを保護
audience にはMCPサーバーのURL(リソースサーバーとしての識別子)を、issuerBaseURL には認可サーバーのURLを入れる。これだけで「トークンなしのリクエスト」を自動で弾けるようになる。
Pythonの場合は python-jose や authlib を使った同様のJWT検証ミドルウェアで実現できる。
ステップ3:ツールごとにスコープで権限を分離する
「全ツール共通の1トークン」ではなく、読み取り専用・書き込み・管理操作で別々のスコープを定義する。
// 認可サーバー側で定義するスコープ例
{
"scopes": {
"mcp:read": "読み取り専用ツールへのアクセス",
"mcp:write": "書き込みツールへのアクセス",
"mcp:admin": "設定変更・管理操作"
}
}
MCPサーバー側でリクエストのスコープを確認し、不十分なスコープのリクエストは 403 Forbidden を返す。セキュリティ専門家が指摘する「最小権限の原則」の実装はこれだ。読み取り専用ツールと書き込みツールを同一トークンで叩ける構成はリスクが高い——この点はFlatt TechのMCPセキュリティ解説でも強調されている(出典:blog.flatt.tech)。
ステップ4:アクセストークンの有効期限と更新を設定する
OAuth 2.1では「短命なアクセストークン + リフレッシュトークン」が推奨構成だ。
- アクセストークンの有効期限:15〜60分(短いほど漏洩時のダメージが小さい)
- リフレッシュトークン:クライアントが自動更新に使う(認可サーバー側のダッシュボードで設定)
Auth0・Entraなどではダッシュボード上でトークン有効期限を設定できる。MCPサーバー側では期限切れトークンに 401 Unauthorized を返す処理が必要だ(express-oauth2-jwt-bearer はこれを自動で処理する)。
ステップ5:監査ログを最小構成で追加する
「誰が・いつ・何のツールを使ったか」を記録する最小構成は、ミドルウェアにログ出力を1行加えるだけでいい。
app.use('/tools', checkJwt, (req, res, next) => {
console.log(JSON.stringify({
ts: new Date().toISOString(),
sub: req.auth?.payload?.sub, // ユーザーID(IdPが発行する識別子)
tool: req.path,
method: req.method,
ip: req.ip,
}));
next();
});
本番環境では console.log ではなく CloudWatch Logs・BigQuery・Datadog などのログ基盤に流す。重要なのは「後から確認できる状態を作ること」であり、最初から豪華なログ基盤を用意する必要はない。
つまずきパターンと対処
「audience不一致」エラーで認証が通らない
最も多いつまずきは、発行したトークンの audience クレームとMCPサーバーが期待する audience 値が一致しないケース。認可サーバー(Auth0など)でクライアント登録時に指定したAPI識別子と、MCPサーバー側の検証コードに書いた audience を1文字単位で照合する。末尾スラッシュの有無でも不一致になる。
CORSエラーが出てブラウザからリクエストできない
MCPサーバーにCORSミドルウェアを追加し、認可サーバーのドメインとクライアントアプリのドメインを許可する。Node.jsなら cors パッケージで2行で解決できる。
リフレッシュトークンが取得できない
Auth0 / Entraでは「Refresh Token Rotation」オプションをONにし、クライアントの offline_access スコープを許可設定に加える必要がある。デフォルトではOFFになっているケースが多いため見落としやすい。
社内IdPとの接続でJWKS(公開鍵セット)が取得できない
社内のIdPがファイアウォール内にある場合、MCPサーバーからIdPの /.well-known/jwks.json エンドポイントへのアウトバウンド通信を開けておく必要がある。ネットワーク担当への連携が必要な落とし穴なので、設定前に確認しておくとよい。
設定ファイルにシークレットをハードコードしてしまう
mcp_config.json や .env にクライアントシークレットをベタ書きしてGitにコミットしてしまうケースは後を絶たない。シークレットは必ず環境変数または Secret Manager(AWS Secrets Manager / Azure Key Vault)に移し、設定ファイルはリポジトリに含めない運用にする。
本番リリース前の確認リスト5項目
以下の5点を本番公開前に必ず目視確認する。
- [ ] 未認証でツールが呼び出せないことを確認——トークンなしのcurlリクエストに
401が返るか実際に叩いて確かめる - [ ] スコープが足りないトークンで
403が返ることを確認——権限分離が実装通りに機能しているかを検証する - [ ] アクセストークンの有効期限が60分以内に設定されているか——本番では15〜30分を目安に設定する
- [ ] 監査ログが記録されているか——ツールを呼び出してログに記録が残るかを目視確認する
- [ ] シークレットが環境変数に入っているか——コード中にハードコードされていないことを
git diffまたはgit log -pで確認する
まとめ——「あとでやる」を今日動かす一歩に変える
MCP×OAuth設定の最大の落とし穴は「複雑そうで後回しにする」という心理だ。しかし実態は「認可サーバー選び → トークン検証ミドルウェア追加 → スコープ設定 → ログ追加」の4ステップで、経験のある開発者なら30分以内に終わる作業量だ。
MCP公式の発表によると、2026年6月18日の仕様更新でOAuth Resource Serverの正式化とセキュリティベストプラクティスが追加され、2026年7月28日に正式RC公開が予定されているとのことだ(現時点の予定であり変更の可能性がある。最新情報はMCP公式ブログで確認してほしい)。今後のMCPエコシステムはOAuth前提の設計が標準になっていく方向だ。
今日やること:使っているIdP(Auth0・Entra・Google Workspaceなど)にOAuthクライアントを1つ登録し、MCPサーバーのテスト環境にトークン検証ミドルウェアを入れてみる。認証が通ったことを確認できれば、本番移行への道は半分以上開いている。
出典・参考リンク
- MCP公式ロードマップ・仕様更新(2026-06-18):https://blog.modelcontextprotocol.io/posts/2026-mcp-roadmap/
- Flatt Tech MCP セキュリティ解説:https://blog.flatt.tech/
- Auth0 公式ドキュメント(OAuth 2.1・設定方法):https://auth0.com/docs
- Microsoft Entra ID(旧Azure AD)OAuth設定:https://learn.microsoft.com/