patchbay audit
·3 min read

The one-field OAuth flag that stops mix-up attacks on your MCP server

There is a one-field flag in your authorization server metadata that decides whether a whole class of OAuth attacks is still possible against your MCP server. Most MCP authorization servers do not set it. The check for it is low severity today. It will not stay that way.

Mix-up attacks in one paragraph

Suppose your MCP client talks to two authorization servers. The user starts a login at server A. An attacker, in the middle somewhere, tricks the client into sending the authorization code to server B instead. Server B happily issues a token the client thinks came from server A. Now the attacker controls what the user signed in with.

This is not theoretical. It is the attack RFC 9207 was written for. The mitigation is a single parameter named iss that the authorization server echoes back on every response. The client checks that the iss value matches the server it thought it was talking to. If it does not, it aborts.

Where metadata comes in

A client cannot validate a parameter it does not know to look for. Authorization servers signal that they will send iss on every response by setting one field in their metadata:

{
  "issuer": "https://auth.example.com",
  "authorization_response_iss_parameter_supported": true,
  "code_challenge_methods_supported": ["S256"]
}

If the field is not there, a spec-compliant client has no reason to validate iss on anything. The mix-up mitigation is off by default because the client cannot assume support.

Where MCP sits

The MCP authorization spec revision 2026-07-28 makes the server side a SHOULD: an MCP authorization server should set the flag and should include iss on every authorization response. The spec also says explicitly that a future revision is expected to raise this to a MUST. So the check is low severity today because the spec says SHOULD. The grade impact will grow.

What the check does

npx -y @patchbay-nebius/agent audit https://mcp.example.com/mcp

ISS-001 reads the authorization server metadata that was already fetched. If authorization_response_iss_parameter_supported is not the boolean true, the check fires low. If it is, the check stays silent.

No active probe. No request to the authorization endpoint. The whole thing is a metadata-only verification, like PKCE-S256 advertisement or the RFC 9728 Protected Resource Metadata presence check.

The fix

One line in your authorization server metadata:

"authorization_response_iss_parameter_supported": true

And then make sure every authorization response the server emits actually carries the parameter, including error responses. Hosted identity providers usually have this as a setting on the app or tenant level. Self-hosted libraries sometimes have it as a configuration flag, sometimes as a code change.

If you also published the PKCE S256 advertisement and a Protected Resource Metadata document, add this one in the same pass. All three live in the same place and clients read all three on the same request.