MCP OAuth 2.0 Workshop
Hello World Dev Conference 2026 · Workshop

MCP OAuth 2.0Workshop

讓 AI Agent、MCP Server 與 CLI 安全登入

MCP Authorization 2026-07-28OAuth 2.0 + PKCESignetKong Gateway
2026/10/14 · 13:30–15:00github.com/go-training/mcp-oauth2-workshop
角色

一次授權,四個參與者

Client

Claude Code
Codex CLI

代表你登入、保管 Token,每次呼叫 MCP 都帶上它。

Browser

瀏覽器
(你)

登入帳號,確認這個 App 要拿哪些權限,按下允許。

Authorization Server

Signet

驗證身分、徵得同意、簽發 Token,公開驗簽用的 JWKS。

Resource Server

MCP Server

持有工具與資料。驗 Token,決定放不放行。

Client ID 是公開識別,不是密碼。CLI 屬於 public Client,沒有 client secret,所以要靠 PKCE 保護登入流程。
MCP OAuth 2.0 Workshop
課程路線

每一關回答一個問題

01
10 分
沒有授權會怎樣?
任何人都能呼叫所有工具
02
15 分
Client 怎麼知道去哪登入?
401 → PRM → AS metadata
03
25 分
怎麼證明你是誰?
Authorization Code + PKCE,Server 驗 JWT
04
20 分
你能做什麼、能去哪?
scope、audience、subject 隔離
06
10 分
多個服務怎麼共用入口?
Kong 集中驗 Token
05
課後選修
撤銷後會立刻失效嗎?
離線驗證的限制
程式是完整可執行的完成版。重點不是手刻 OAuth,而是看懂每個請求、每一次拒絕代表什麼。
MCP OAuth 2.0 Workshop
Lab 01 · 沒有授權

MCP Server 只是一個 HTTP 端點

Lab 01 的 Server 不檢查任何東西,所以呼叫一定成功。

  • 不知道呼叫者是誰
  • 分不出讀取與寫入
  • 能連到這個 port 的程式,就能用全部工具

工具:whoami、list_notes、create_note。筆記存在記憶體裡。

MCP OAuth 2.0 Workshop
Lab 02 · 概念

兩份 metadata,把 Client 帶到登入頁

MCP Server GET /.well-known/oauth-protected-resource/mcp
{ "resource": "http://localhost:8000/mcp", "authorization_servers": [ "https://signet.wu-boy.com" ] }

Protected Resource Metadata(PRM):我是哪個資源、信任哪個 Authorization Server。這是 MCP Server 自己的端點,不是另一台伺服器。

Signet GET AS metadata(依 issuer 建構)
{ "issuer": "https://signet.wu-boy.com", "authorization_endpoint": "…", "token_endpoint": "…", "jwks_uri": "…", "code_challenge_methods_supported": ["S256"] }

AS metadata:去哪登入、去哪換 Token、去哪拿公鑰,以及支援哪種 PKCE。

MCP OAuth 2.0 Workshop
Lab 02 · Sequence

Authorization Server Discovery

Lab 02 到此結束,不需要登入。這一關即使帶有效 Token 也回 401。
Lab 03 · 概念

PKCE:先給鎖頭,最後才拿出鑰匙

code_verifier

Client 產生的隨機字串,一直留在 Client 手上。

→SHA-256
base64url
code_challenge

放進授權網址,讓 Signet 先記下來。method=S256

授權階段

只送 challenge

瀏覽器帶回的是授權碼 code,還不是 Token。

換 Token 階段

送出 verifier

Signet 確認 SHA-256(verifier) 等於當初的 challenge。攔截到 code 的人沒有 verifier,換不到 Token。

同一個流程還有兩道檢查:state 確認 callback 屬於這次登入;iss(RFC 9207)確認回應來自預期的 Authorization Server。
MCP OAuth 2.0 Workshop
Lab 03 · Sequence 1/2

登入授權:瀏覽器帶回的是 code,不是 Token

授權網址只帶 code_challenge;verifier 留在 Client。
Lab 03 · Sequence 2/2

換 Token,然後帶 Token 呼叫 MCP

瀏覽器登入狀態不會自動附到 MCP 請求;每次呼叫都要帶 Access Token。
Lab 03 · 概念

MCP Server 收到 Token 後問五個問題

Access Token payload 示意,非實際內容
// header: alg RS256, kid → 從 JWKS 找公鑰 { "iss": "https://signet.wu-boy.com", "aud": "http://localhost:8000/mcp", "sub": "練習帳號識別值", "exp": 到期時間, "type": "access", "scope":"notes:read" }
簽章用 Signet 的 JWKS 驗 RS256,確認沒被竄改
iss是不是我信任的 Signet 簽發的?
aud是不是發給我這台 Server 的?
exp過期了沒有?
type必須是 access;refresh token 或 ID token 不能呼叫 MCP
sub通過後,用它辨識「你是誰」,whoami 回傳的就是它
RS256 + JWKS 是本教材的選擇;MCP 規範並未強制使用 JWT。
Lab 04 · 概念

401 和 403 是兩種不同的「不行」

401
Unauthorized

我無法接受這顆 Token

  • 沒帶 Token,或 Token 無效、過期
  • aud 不符:這顆 Token 是發給別台 Server 的
怎麼辦 為這台 Server 的 resource 重新取得 Token
403
insufficient_scope

我知道你是誰,但你不能做這件事

  • Token 有效、身分確定
  • 只有 notes:read,卻呼叫 create_note
怎麼辦 用更多 scope 重新授權;舊 Token 不會自動升級
第三道邊界是 subject:同一台 Server、同樣的權限,不同帳號仍只看得到自己的筆記。
MCP OAuth 2.0 Workshop
Lab 04 · Sequence

scope:讀得到,不代表寫得進去

notes:read 控制入口,notes:write 控制寫入工具。
Lab 04 · Sequence

audience:A 的 Token 打不進 B

同一個帳號、同樣的 scope,換一台 Server 就要一顆新的 Token。
Lab 06 · 概念

入口驗證交給 Gateway,業務權限留在服務

Signet

發 Token

  • 使用者登入與同意授權
  • 簽發 Token
  • 公開 JWKS
Kong + mcp-oauth2

守入口

  • 回 401 challenge、提供 PRM
  • 驗 JWT:簽章、iss、aud、exp
  • 檢查入口 scope notes:read
MCP Backend

管工具與資料

  • 驗 Gateway 共享憑證與身分 headers
  • create_note 仍要求 notes:write
  • 依 subject 隔離資料
信任邊界 backend 不對外發布 port,只在私有網路接收 Kong 的請求。只送一個 X-MCP-Subject: admin header 騙不過它。
取捨 Gateway 多一個要維運的服務。只有一台 MCP Server 時,Lab 04 的自行驗證仍然適用。
MCP OAuth 2.0 Workshop
Lab 06 · Sequence 1/2

Kong 守入口:401、PRM 與 JWT 驗證

Kong 不代替使用者登入;登入仍由 Client 向 Signet 完成。
Lab 06 · Sequence 2/2

入口通過,不代表能用所有工具

Kong 驗入口,MCP backend 管工具與資料權限。
Lab 05 · 課後選修

撤銷成功 ≠ 立刻被拒絕

本教材的 Server 與 Kong plugin 都離線驗 JWT,不會每次向 Signet 查撤銷狀態。

  • 撤銷不改變簽章,未過期的 Token 仍可能通過
  • RFC 7009:已撤銷或未知的 Token 也可能回 200
  • 需要即時拒絕時,再設計 introspection 或其他撤銷傳播機制
public Client 撤銷只需 client_id 與 Token,不需要 secret。
重點回顧

帶走這七件事

401 + PRM 告訴 Client 去哪登入;Server 不代替 Client 登入
public Client 沒有 secret,靠 PKCE 保護授權碼
每次呼叫 MCP 都要帶 Access Token
Server 驗簽章、iss、aud、exp、type
401 是 Token 不被接受;403 是權限不夠
Gateway 集中入口驗證,工具與資料權限仍留在服務
撤銷不等於立即失效,離線驗證要另外處理
MCP OAuth 2.0 Workshop
Q&A

Q&A

教材

github.com/go-training/
mcp-oauth2-workshop

規範

modelcontextprotocol.io
Authorization 2026-07-28

Gateway

github.com/go-signet/
kong-mcp-oauth2

MCP OAuth 2.0 Workshop