OAuth 2.0 測試實戰(Mock Provider + Inspector):用 Bearer Token 保護 MCP SSE
OAuth 2.0 測試實戰(Mock Provider + Inspector):用 Bearer Token 保護 MCP SSE
這篇文章把本 repo 的 OAuth 2.0 測試流程整理成一條可重現的路徑,涵蓋:
- 用 OAuth 2.0 Authorization Code + PKCE 取得 access_token
- 用 userinfo endpoint 驗證 Bearer token,保護
GET /sse與POST /messages - 用 MCP Inspector 連線(含常見「為什麼會打到 http://localhost:3000/authorize?」的坑)
本文對應程式在:
- [server.ts](file:///home/iantp/GitHub/2601-mcp-test-08/server.ts)
- [README.md](file:///home/iantp/GitHub/2601-mcp-test-08/README.md)
0. 你會用到的端點
你的 MCP Server(localhost)
GET /sse:建立 MCP SSE 連線(需要 Bearer token)POST /messages?sessionId=...:送 JSON-RPC 訊息(需要同一顆 Bearer token)
你的 OAuth 測試頁(localhost)
GET /oauth:顯示 OAuth 設定與「開始登入」連結GET /oauth/login:產生state+ PKCE(S256),導向 OAuth Provider 的授權頁GET /oauth/callback:用code換 token,並(若有設定)打 userinfo
OAuth Provider(這次用 Cloudflare 上的 mock)
Mock OAuth Server:
https://oauth.aicodecleanup.us/- OIDC Discovery:
https://oauth.aicodecleanup.us/.well-known/openid-configuration
1. 先把 server 跑起來(指向 mock provider)
用 OIDC Discovery(最省事):
OAUTH_ISSUER=https://oauth.aicodecleanup.us/ \
OAUTH_CLIENT_ID=test_client_id \
OAUTH_CLIENT_SECRET=test_client_secret \
bun run server
如果你不想用 issuer,也可以手動指定 endpoints(本 repo 也支援別名):
OAUTH_CLIENT_ID=test_client_id \
OAUTH_CLIENT_SECRET=test_client_secret \
OAUTH_AUTH_URL=https://oauth.aicodecleanup.us/authorize \
OAUTH_TOKEN_URL=https://oauth.aicodecleanup.us/token \
OAUTH_USERINFO_URL=https://oauth.aicodecleanup.us/userinfo \
bun run server
2. 用瀏覽器跑一次 OAuth 2.0(確認 provider 能用)
- 打開:
http://localhost:3000/oauth
- 點「開始登入」,完成授權後會回到 callback 頁,看到兩段 JSON:
- Token Response(
access_token/refresh_token/expires_in/scope) - Userinfo(若 provider 支援且有 access_token)
如果你看到 Missing OAUTH_CLIENT_ID,代表 server 沒吃到 OAUTH_CLIENT_ID。你也可以臨時用:
http://localhost:3000/oauth?client_id=test_client_id
3. /sse 的 Bearer token 保護:驗什麼、怎麼驗?
這個 repo 目前採用「用 userinfo endpoint 驗 token」的策略:
GET /sse:- 必須帶
Authorization: Bearer <token> - server 會呼叫 OAuth 的
userinfo來驗證 token(成功才建立 SSE)
- 必須帶
POST /messages:- 同樣必須帶
Authorization: Bearer <token> - 且 token 必須與建立該 session 的 token 一致(防止不同 token 混用同一 sessionId)
- 同樣必須帶
你可以用 curl 快速檢查(先把 token 換成你自己的):
curl -N -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' http://127.0.0.1:3000/sse
如果沒帶 token,預期會看到:
Missing Authorization: Bearer
4. 用 Inspector 連 MCP SSE:兩條路徑
路徑 A(最穩):先用 /oauth 拿 token,再貼到 Inspector
- 先用瀏覽器跑
http://localhost:3000/oauth,複製access_token - 打開 Inspector,Transport 選 SSE、URL 填:
http://localhost:3000/sse
- Authentication → Custom Headers:
Authorization: Bearer <access_token>
記得把 header 左邊的 toggle 打開(沒打開不會送出)。
路徑 B:用 Inspector 內建 OAuth Flow(容易踩坑,但已提供解法)
某些 Inspector 版本會把 OAuth provider「視為」你填的 MCP server 同源,因此它會去打:
http://localhost:3000/authorizehttp://localhost:3000/tokenhttp://localhost:3000/userinfo
如果你的 server 沒有這些路由,就會看到 404 Not Found。為了讓這條路徑能跑,本 repo 已在 server.ts 補上 proxy:
GET /authorize:redirect 到 upstream 的 authorization_endpointPOST /token:proxy 到 upstream token_endpointGET /userinfo:proxy 到 upstream userinfo_endpointGET /.well-known/openid-configuration//.well-known/oauth-authorization-server:回傳 localhost 的 proxy metadata
因此就算 Inspector 「打錯地方」(打到 localhost),localhost 也會把它導到真正的 provider。
5. 常見錯誤排查
5.1 你在瀏覽器打 https://oauth.aicodecleanup.us/token 看到 404
多半是因為你用瀏覽器做了 GET。token endpoint 正確用法是 POST(application/x-www-form-urlencoded),本 repo 在 callback 換 token 是用 POST,所以可以成功。
5.2 Inspector 跳到 http://localhost:3000/authorize?... 然後 404
代表 Inspector 目前把 provider 當 localhost。這個 repo 已提供 /authorize proxy,更新後應該不會再 404。
5.3 redirect_uri 不被允許
Inspector 的 redirect 通常是 http://localhost:6274/oauth/callback。如果 provider 需要白名單 redirect URI,而你沒有權限配置 provider,就改走「路徑 A」:用 http://localhost:3000/oauth 拿 token,再貼到 Inspector。
6. 最終驗收:在 Inspector 呼叫 echo_tool
連線成功後:
- list tools 應該看到
echo_tool - call tool:
{
"message": "Hello from Inspector!"
}
預期回應類似:
Server received via SSE: Hello from Inspector!
- ← Previous
MCP SSE(Bun + Hono)實作筆記:Header 認證與 Inspector 測試 - Next →
深入理解 OAuth 2.0:從 Client ID 到 Token Exchange