Skip to content

sep-1932 authorization-server scenario: dpop_jkt enforcement is untested (RFC 9449 §10) #549

Open

Description

@PieterKas

Gap

The AS acceptance suite never exercises authorization code binding. dpop_jkt does not appear anywhere in src/scenarios/authorization-server/ on main, so an AS that silently ignores the parameter — issuing a token for a jkt-bound code exchanged with a wrong-key proof — passes the suite today.

The attack this binding exists to stop: an attacker who steals an authorization code (referrer leak, log, open redirect) exchanges it with a DPoP proof from their own key. A conformant AS compares the proof key's thumbprint to the dpop_jkt from the authorization request and rejects; an AS that ignores the parameter issues the attacker a token bound to the attacker's key.

#523 adds the client side of this (does the client send dpop_jkt), and its test AS enforces the binding — but nothing tests a real AS under test for the enforcement itself. The counterpart SEP text (client SHOULD) is in modelcontextprotocol/ext-auth#35.

Spec text

RFC 9449 §10:

When a token request is received, the authorization server computes the JWK Thumbprint of the proof-of-possession public key in the DPoP proof and verifies that it matches the dpop_jkt parameter value in the authorization request. If they do not match, it MUST reject the request.

https://www.rfc-editor.org/rfc/rfc9449.html#section-10

Proposal

Add two probes to the authorization-server DPoP scenario (builds on the surface #525 touches). Both run the full flow with dpop_jkt = thumbprint of key A on the authorization request, then vary the token exchange:

Check Token exchange SUCCESS WARNING FAILURE
sep-1932-as-dpop-jkt-accepted valid proof from key A token issued — request rejected (RFC 6749 §3.1: unrecognized request parameters MUST be ignored, so rejecting the matching flow breaks every client that sends the parameter)
sep-1932-as-dpop-jkt-mismatch-rejected valid proof from key B request rejected token issued — binding not enforced —

Grading rationale for the WARNING: authorization code binding is a SHOULD in the MCP profile (modelcontextprotocol/ext-auth#35) and the dpop_jkt parameter is OPTIONAL in RFC 9449 §10, so an AS that issues a token on the mismatch has either not implemented an optional mechanism or implemented it without enforcement — indistinguishable from outside, and both correctly graded WARNING. This mirrors the client side in #523, where omitting dpop_jkt is likewise a SHOULD miss graded WARNING. An AS that rejects the mismatched exchange is enforcing RFC 9449 §10's MUST and passes.

@nbarbettini, flagging this issue as a natural follow-up to #523 / #525 once both land as the dpop_jkt tests don't cover AS scenarios at present.

Generated with the aid of Claude (Fable 5).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions