Server Auth: DPoP Proof Validation (SEP-1932)
维护者通常 4 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 5/5
- 预计耗时
- 一周以上
- 新手友好度
- 45/100
- Issue 类型
- 功能
- 描述清晰度
- 基本清楚
- 活跃度
- 冷清
- 技术栈
- typescript
- 领域
- api, authentication, security, testing-qa
调研方向
从 src/scenarios/server/ 下现有的场景注册、helpers/ 区域和 createAuthServer 开始;阅读 RFC 9449 §4.3,并运行 npm test 以了解一致性测试框架。添加一个已注册的服务器场景、proof 和 token fixtures,以及覆盖所列正向和负向检查的 helper 单元测试。当标准 CLI runner 和 npm test 通过,并满足必需的 status、challenge 和 error 断言时,即视为完成。
由索引模型根据 Issue 内容生成。
描述
Overview
SEP-1932
adopts OAuth 2.0 Demonstrating Proof of Possession
(RFC 9449) as an optional MCP
authorization extension for sender-constrained access tokens. When a client
presents a DPoP-bound token, the MCP server (resource server) must verify a
DPoP proof on every request before granting access.
This issue covers MCP server conformance only. It validates that a server
acting as an OAuth 2.1 resource server correctly applies the RFC 9449 §4.3 proof
checking steps, enforces the ±5-minute iat acceptance window, returns correct
401 / WWW-Authenticate: DPoP challenges, and continues to enforce the baseline
token audience requirements.
Key properties of the server role:
- The framework drives the server as a DPoP client, presenting valid proofs
for positive checks and deliberately malformed proofs for negative checks. - The proposal adopts DPoP as defined in RFC 9449 — no MCP-specific extensions
to proof validation are expected. - A conformant stateless server provides replay protection via the
iatwindow
and standard claim validation;jtitracking and nonces are optional.
Specification References
- SEP-1932 PR: https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1932
- Detailed proposal: https://github.com/modelcontextprotocol/ext-auth/blob/pieterkas-dpop-extension/specification/draft/dpop-extension.mdx
- RFC 9449 — OAuth 2.0 Demonstrating Proof of Possession (DPoP): https://www.rfc-editor.org/rfc/rfc9449.html
- §4.2 DPoP Proof JWT Syntax, §4.3 Checking DPoP Proofs (the core checklist)
- §6 Public Key Confirmation (
cnf/jkt), §7 DPoP-bound access tokens - §7.1 The DPoP Authentication Scheme and
WWW-Authenticatechallenge - §9 Resource Server-Provided Nonce, §11.1 DPoP Proof Replay
- Baseline MCP Authorization specification (resource-server token validation and
audience binding): https://modelcontextprotocol.io/specification/draft/basic/authorization
Scope
In scope — what the MCP/resource server does:
- Requiring the
DPoPAuthorizationscheme and aDPoPproof header on
protected requests. - Applying every RFC 9449 §4.3 proof-checking step.
- Enforcing the ±5-minute
iatacceptance window. - Confirming the access token is bound to the proof key (
cnf/jktagreement). - Returning correct
401responses with aWWW-Authenticate: DPoPchallenge
(including thealgsparameter and the appropriateerrorcode). - Optional server-provided nonce issuance and enforcement.
- Continuing to enforce baseline token audience validation when DPoP is used.
Not in scope (covered elsewhere or by another role):
- Client proof construction and nonce-retry behaviour — covered by the client
conformance issue. - Authorization-server token binding, metadata, and token-endpoint nonce —
covered by the authorization-server conformance issue. - Cryptographic algorithm policy beyond rejecting
none/symmetric algorithms.
Changes Required
Conformance harness (framework acting as a DPoP client)
- The framework, acting as a DPoP client, presents a DPoP-bound access
token (Authorization: DPoP <token>) plus aDPoPproof to the server under
test. - Fixture generation for: a valid key pair, a DPoP-bound access token whose
cnf.jktmatches the proof key and whose audience matches the server under
test, and a matched valid proof. - A library of crafted invalid proofs, one per §4.3 failure mode, each
designed to trigger a specific rejection so the server's response is
predetermined.
Test authorization server (createAuthServer)
- Mint DPoP-bound access tokens (correct audience,
cnf.jkt) for the server under
test to validate. Only needed to the extent the server requires a trusted,
audience-correct token to reach the proof-validation path.
Helpers (helpers/)
- DPoP proof builder with per-field overrides (so each negative fixture can
perturb exactly one claim/header: wronghtu, wronghtm, stale/futureiat,
missingjti,typ != dpop+jwt,alg=none/symmetric, private key injwk,
bad signature, wrong/absentath, duplicateDPoPheader, mismatched
cnf/jkt). - JWK SHA-256 thumbprint and
athhelpers.
Scenario (src/scenarios/server/)
- A single scenario file implementing all checks below, registered in the server
scenario list.
Acceptance test suite
- Helper unit tests (proof builder field overrides, thumbprint,
ath), and
scenario acceptance tests asserting each check passes for a conformant server
and fails for a deliberately non-conformant one.
Components that do not change
- The MCP protocol/JSON-RPC interaction is unchanged; only the
Authorization
scheme and the addedDPoPproof verification differ.
Checks to Cover
Positive (valid proof accepted)
- A request with a valid DPoP-bound token and matching proof is accepted and
the MCP operation succeeds. - Server accepts a proof whose
iatis within the ±5-minute window.
Negative (RFC 9449 §4.3 — each rejected with 401 + WWW-Authenticate: DPoP error="invalid_dpop_proof" unless noted)
- More than one
DPoPheader field present. -
DPoPheader is not a single, well-formed JWT. - A required claim is missing (
jti,htm,htu,iat). -
typJOSE header is notdpop+jwt. -
algisnoneor a symmetric algorithm (or otherwise unacceptable). - Signature does not verify against the embedded
jwk. -
jwkJOSE header contains a private key. -
htmdoes not match the request method. -
htudoes not match the request target URI (ignoring query/fragment). -
iatis outside the acceptable window (stale and far-future both rejected). -
athis missing or does not equal the hash of the presented access token. - The access token's bound key (
cnf.jkt) does not match the proof's public
key → rejected witherror="invalid_token". - A DPoP-bound token presented with the
Bearerscheme is rejected. - Baseline: a token whose audience is not this server is rejected (
401),
even with an otherwise valid proof.
Optional nonce behaviour (only if the server advertises/requires nonces)
- Server issues
401 ... error="use_dpop_nonce"with aDPoP-Nonceheader
when it requires a nonce and none is present. - Server accepts the subsequent request carrying the matching
nonceclaim. - Server rejects a proof whose
noncedoes not match a recently supplied
value.
Challenge format
-
401responses carryWWW-Authenticate: DPoPand SHOULD include thealgs
parameter listing acceptable JWS algorithms.
Acceptance Criteria
- A single scenario file in
src/scenarios/server/implements all checks
above (one scenario, many checks). - Each §4.3 check has both a passing case (valid proof accepted) and a
deliberate failing case (crafted invalid proof rejected with the correct
status and error code) proven by the automated acceptance test suite. - Helper unit tests cover the proof builder's per-field overrides and the
thumbprint/athhelpers. - The acceptance test suite runs as part of
npm test. - Scenario runs through the standard CLI runner; no parallel entry point is
introduced. - Validated against at least one real SDK server implementation before the PR
is submitted; SDK baseline YAMLs updated where existing SDKs do not yet
support DPoP.
Out of Scope
- Required
jtistate-tracking / global replay store — optional per RFC 9449
§11.1. A stateless server relying on theiatwindow and claim validation is
conformant;jti-tracking is tested only as optional behaviour if advertised. - Server-side nonce cryptographic construction (e.g. AEAD-encrypted
timestamps) — an implementation choice; only the observable nonce challenge/
acceptance protocol is tested. - Client proof construction and authorization-server behaviour — covered by the
separate client and authorization-server conformance issues.
Notes
Prepared with the aid of Claude (Opus 4.8)
- 主要语言
- TypeScript
- 星标
- 127
- 派生
- 107
- 平均合并
- 4 天 22 小时
- 30 天内合并 PR
- 5
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
modelcontextprotocol/conformance 的其他 Issue
-
难度 2/5 1-3 小时 新手友好度 88/100
modelcontextprotocol/conformance#531 · 1 条评论 ·
维护者通常 4 天内回复
-
难度 2/5 1-3 小时 新手友好度 68/100
modelcontextprotocol/conformance#530 ·
维护者通常 4 天内回复
-
难度 2/5 1-3 小时 新手友好度 75/100
modelcontextprotocol/conformance#519 ·
维护者通常 4 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 72/100
modelcontextprotocol/conformance#315 · 1 条评论 ·
维护者通常 4 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 68/100
modelcontextprotocol/conformance#312 · 1 条评论 ·
维护者通常 4 天内回复
查看 modelcontextprotocol/conformance 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复
-
automated issue report
难度 1/5 1 小时以内 新手友好度 68/100
-
documentation
难度 1/5 1 小时以内 新手友好度 92/100
github/copilot-sdk#2804 · 1 条评论 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 62/100
drizzle-team/drizzle-orm#6418 ·
维护者通常 4 天内回复
-
难度 1/5 1 小时以内 新手友好度 92/100
diegosouzapw/OmniRoute#15307 · 1 条评论 ·
维护者通常 2 天内回复