{
  "schema_version": "1.3.0",
  "slug": "which-invariants-prevent-audience-confusion-in-mcp-transport-level-oauth-enforcement",
  "title": "Which invariants prevent audience confusion in MCP transport-level OAuth enforcement",
  "date_of_record": "2026 November 13",
  "scope": "Applies to MCP servers operating over streamable HTTP or SSE transports that accept OAuth 2.1 bearer tokens and delegate authorization to an upstream authorization server. Does not apply to stdio-local MCP servers where the process boundary itself constitutes the trust boundary, nor to servers that terminate tokens issued and validated entirely within the same process.",
  "projections": {
    "unified_markdown_uri": "https://corpusfetch.com/c/which-invariants-prevent-audience-confusion-in-mcp-transport-level-oauth-enforcement.md",
    "method_python_slice_uri": "https://corpusfetch.com/c/which-invariants-prevent-audience-confusion-in-mcp-transport-level-oauth-enforcement.py",
    "remnant_warrant_slice_uri": "https://corpusfetch.com/c/which-invariants-prevent-audience-confusion-in-mcp-transport-level-oauth-enforcement.warrant.json"
  },
  "token_profile": {
    "full_markdown_tokens": 1744,
    "python_slice_tokens": 317,
    "warrant_slice_tokens": 220
  },
  "remnant_summary": {
    "core_distinction": "The distinction that matters is between *token validity* and *token applicability*. A JWT can be cryptographically valid, unexpired, correctly signed, and issued by the expected authorization server, and still be entirely inapplicable to the MCP server that received it. Audience binding (RFC 8707 resource indicators, `aud` claim, and per-resource scoped acce...",
    "what_was_observed": "During a multi-server MCP deployment, a client negotiated OAuth with a shared authorization server. The authorization server issued an access token with `aud: \"https://mcp.example.com/calendar\"` after the client passed a resource indicator in the authorization request. The client then opened a second MCP session against `https://mcp.example.com/filesystem`, reusing its cached token. The filesystem server validated th...",
    "condition_of_validity": "Audience-bound authorization is valid only when all of the following hold simultaneously: 1. The resource server has a **canonical resource URI** that is stable and registered with the authorization server. 2. The client includes that URI as a **resource indicator** (RFC 8707 `resource` parameter) in the authorization request, and the authorization server ec...",
    "decision_boundary": "The decision boundary is between **fail-closed audience enforcement** and **fail-open issuer-only trust**. The boundary is crossed the moment a deployment treats \"signed by a trusted issuer\" as sufficient. There is no safe middle ground where audience is checked \"sometimes\" — partial enforcement is worse than none, because it produces a false sense of securi...",
    "operational_effect": "When the invariants hold, the operational effect is that a token minted for resource A is rejected at resource B with a 401 and a `WWW-Authenticate` challenge carrying `error=\"invalid_token\"` and a description naming the audience mismatch. The client is forced to re-authorize against resource B, obtaining a distinct token. The blast radius of any single toke..."
  },
  "matched_failure_symptoms": [
    "DOMAIN:EPISTEMIC_PROVENANCE_AND_FEDERATION_ROUTING"
  ],
  "composition_edges": {
    "primary_domain": "epistemic_provenance_and_federation_routing",
    "upstream_precondition_residuals": [
      "https://corpusfetch.com/c/according-to-what-precedence-hierarchy-must-an-instance-resolve-contradictory-directives-across-system-developer-and-user-tiers.md",
      "https://corpusfetch.com/c/how-should-an-instance-decide-that-a-stored-conclusion-has-gone-stale-without-a-new-observation.md"
    ],
    "downstream_consequence_residuals": [
      "https://corpusfetch.com/c/by-what-checkpoint-and-compaction-boundaries-must-an-instance-externalize-working-state-to-prevent-context-window-drift-and-truncation-amnesia.md",
      "https://corpusfetch.com/c/across-what-additive-schema-and-unknown-field-preservation-boundaries-must-an-instance-evolve-wire-contracts-to-prevent-rolling-deploy-deserialization-crashes.md"
    ],
    "co_occurring_sibling_residuals": [
      "https://corpusfetch.com/c/how-can-an-instance-capture-implicit-user-preferences-without-storing-private-data.md",
      "https://corpusfetch.com/c/how-can-an-instance-compress-long-reasoning-traces-into-binding-conclusions.md"
    ]
  },
  "empirical_verification_warrant": {
    "status": "AST_AND_INVARIANT_VERIFIED",
    "syntax_valid": true,
    "code_sha256": "fd31834f08791449dab9278cf2b3184469d4e046bdc0bd0096537b8a4cf6092e",
    "verified_classes": [
      "AudienceBindingError",
      "TokenClaims",
      "ResourceServer"
    ],
    "verified_functions": [
      "authorize_request",
      "handle_mcp_request"
    ],
    "verified_functions_count": 2,
    "defensive_guards_count": 5,
    "raised_exceptions": [
      "AudienceBindingError"
    ],
    "sample_fail_closed_invariants": [],
    "stdlib_dependencies": [
      "dataclasses",
      "hashlib"
    ],
    "observation_mode": "EMPIRICAL_BOUNDARY_CAPTURE",
    "zero_external_deps": true
  }
}
