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
iat window
and standard claim validation; jti tracking and nonces are optional.
Specification References
Scope
In scope — what the MCP/resource server does:
- Requiring the
DPoP Authorization scheme and a DPoP proof header on
protected requests.
- Applying every RFC 9449 §4.3 proof-checking step.
- Enforcing the ±5-minute
iat acceptance window.
- Confirming the access token is bound to the proof key (
cnf/jkt agreement).
- Returning correct
401 responses with a WWW-Authenticate: DPoP challenge
(including the algs parameter and the appropriate error code).
- 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 a DPoP proof to the server under
test.
- Fixture generation for: a valid key pair, a DPoP-bound access token whose
cnf.jkt matches 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: wrong htu, wrong htm, stale/future iat,
missing jti, typ != dpop+jwt, alg=none/symmetric, private key in jwk,
bad signature, wrong/absent ath, duplicate DPoP header, mismatched
cnf/jkt).
- JWK SHA-256 thumbprint and
ath helpers.
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 added DPoP proof verification differ.
Checks to Cover
Positive (valid proof accepted)
Negative (RFC 9449 §4.3 — each rejected with 401 + WWW-Authenticate: DPoP error="invalid_dpop_proof" unless noted)
Optional nonce behaviour (only if the server advertises/requires nonces)
Challenge format
Acceptance Criteria
Out of Scope
- Required
jti state-tracking / global replay store — optional per RFC 9449
§11.1. A stateless server relying on the iat window 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)
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
iatacceptance window, returns correct401/WWW-Authenticate: DPoPchallenges, and continues to enforce the baselinetoken audience requirements.
Key properties of the server role:
for positive checks and deliberately malformed proofs for negative checks.
to proof validation are expected.
iatwindowand standard claim validation;
jtitracking and nonces are optional.Specification References
cnf/jkt), §7 DPoP-bound access tokensWWW-Authenticatechallengeaudience binding): https://modelcontextprotocol.io/specification/draft/basic/authorization
Scope
In scope — what the MCP/resource server does:
DPoPAuthorizationscheme and aDPoPproof header onprotected requests.
iatacceptance window.cnf/jktagreement).401responses with aWWW-Authenticate: DPoPchallenge(including the
algsparameter and the appropriateerrorcode).Not in scope (covered elsewhere or by another role):
conformance issue.
covered by the authorization-server conformance issue.
none/symmetric algorithms.Changes Required
Conformance harness (framework acting as a DPoP client)
token (
Authorization: DPoP <token>) plus aDPoPproof to the server undertest.
cnf.jktmatches the proof key and whose audience matches the server undertest, and a matched valid proof.
designed to trigger a specific rejection so the server's response is
predetermined.
Test authorization server (
createAuthServer)cnf.jkt) for the server undertest to validate. Only needed to the extent the server requires a trusted,
audience-correct token to reach the proof-validation path.
Helpers (
helpers/)perturb exactly one claim/header: wrong
htu, wronghtm, stale/futureiat,missing
jti,typ != dpop+jwt,alg=none/symmetric, private key injwk,bad signature, wrong/absent
ath, duplicateDPoPheader, mismatchedcnf/jkt).athhelpers.Scenario (
src/scenarios/server/)scenario list.
Acceptance test suite
ath), andscenario acceptance tests asserting each check passes for a conformant server
and fails for a deliberately non-conformant one.
Components that do not change
Authorizationscheme and the added
DPoPproof verification differ.Checks to Cover
Positive (valid proof accepted)
the MCP operation succeeds.
iatis within the ±5-minute window.Negative (RFC 9449 §4.3 — each rejected with
401+WWW-Authenticate: DPoP error="invalid_dpop_proof"unless noted)DPoPheader field present.DPoPheader is not a single, well-formed JWT.jti,htm,htu,iat).typJOSE header is notdpop+jwt.algisnoneor a symmetric algorithm (or otherwise unacceptable).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.cnf.jkt) does not match the proof's publickey → rejected with
error="invalid_token".Bearerscheme is rejected.401),even with an otherwise valid proof.
Optional nonce behaviour (only if the server advertises/requires nonces)
401 ... error="use_dpop_nonce"with aDPoP-Nonceheaderwhen it requires a nonce and none is present.
nonceclaim.noncedoes not match a recently suppliedvalue.
Challenge format
401responses carryWWW-Authenticate: DPoPand SHOULD include thealgsparameter listing acceptable JWS algorithms.
Acceptance Criteria
src/scenarios/server/implements all checksabove (one scenario, many checks).
deliberate failing case (crafted invalid proof rejected with the correct
status and error code) proven by the automated acceptance test suite.
thumbprint/
athhelpers.npm test.introduced.
is submitted; SDK baseline YAMLs updated where existing SDKs do not yet
support DPoP.
Out of Scope
jtistate-tracking / global replay store — optional per RFC 9449§11.1. A stateless server relying on the
iatwindow and claim validation isconformant;
jti-tracking is tested only as optional behaviour if advertised.timestamps) — an implementation choice; only the observable nonce challenge/
acceptance protocol is tested.
separate client and authorization-server conformance issues.
Notes
Prepared with the aid of Claude (Opus 4.8)