Skip to content

fix(auth): A2A cannot express task-level discovery access — spec designates three operations publicly accessible #1010

Description

@numarasSigmaSoftware

AdCP 3.1.1 designates a set of low-risk discovery operations as publicly accessible:

dist/docs/3.1.1/building/by-layer/L1/security.mdx — "### Low-Risk Operations (Discovery) / These operations are publicly accessible:" listing get_adcp_capabilities (agent capability discovery), get_products (public inventory discovery), and list_creative_formats (public format catalog).

The MCP leg can express this — BearerTokenAuth.mcp_discovery_tools is a per-tool allowlist (adcp/server/auth.py:1018, documented at :917-932). The A2A leg has no equivalent: A2ABearerAuthMiddleware exempts only the two well-known agent-card paths (auth.py:1411-1414, _A2A_DISCOVERY_PATHS at :1334-1340) and never inspects the JSON-RPC body to see which skill is being invoked. The only other lever, allow_unauthenticated, is all-or-nothing for the whole endpoint (auth.py:1420-1422).

So on A2A an adopter must choose between:

  • authenticating everything — a buyer cannot discover capabilities, products, or formats without credentials, contrary to the spec text above; or
  • authenticating nothing on /a2a — every mutating skill becomes unauthenticated.

Neither is conformant for an agent that wants spec-correct discovery plus protected writes.

Proposed change: an a2a_discovery_skills allowlist mirroring mcp_discovery_tools, evaluated against the skill name(s) in the request body. Two semantics worth deciding explicitly, from our own implementation experience: a message may carry more than one skill (any non-discovery skill should require auth), and an unauthenticated rejection should still carry a spec-shaped AdCP error envelope rather than only an HTTP-level 401, so buyers get a machine-readable AUTH_REQUIRED code.

Verified present on 6.6.0 and v7.0.0-rc (the A2A module is byte-identical between them).

Happy to contribute the implementation if the shape sounds right.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions