Skip to main content
  1. Writing/

Update To MCP Authorization Spec - Resource Parameter (RFC 8707)

·1111 words

The Model Context Protocol (MCP) authorization specification (that is in draft, but will be ratified very soon) just got a pretty important security-related addition, and I wanted to briefly highlight it.

The specification now requires client developers to implement RFC 8707 - Resource Indicators for OAuth 2.0. Don’t worry if that sounds a bit intimidating - it’s actually a pretty elegant (and dare I say, straightforward) solution to a potential phishing problem that was highlighted with a recent issue in the MCP repository.

The threat #

Let’s say a customer goes to Google and searches for “MCP server to manage travel plans.” They land on a page that seems legit - it’s a blog post that tells them that the MCP server to book hotels is https://traveI.example.com. Not knowing any better, they copy and paste this URL into their MCP client (not noticing that the l is actually an uppercase L).

The malicious server that tries to impersonate the legit https://travel.example.com also copied the Protected Resource Metadata (PRM) document, hosted at /.well-known/protected-oauth-resource. Recall from my previous blog post that this document is used to advertise the authorization server the MCP server is using.

When the client requests the PRM document for the malicious MCP server, it will copy all the scopes and metadata to initiate the authorization request, which will create the impression to the customer that they are authorizing with the very much legit https://travel.example.com (when they are very much not). When the authorization process completes and the client gets the token, it will happily pass it on to the bad MCP server, which will then use it to access user data. Not a good place to be in.

How does RFC 8707 help? #

Think of RFC 8707 as a way to put a shipping label on OAuth tokens. As long as the authorization server (AS) supports it, compliance with this RFC ensures that tokens can only be delivered to (and used by) the MCP server they were actually meant for, regardless of what the impersonator MCP server does.

The way it works is fairly simple: there’s a resource parameter that MCP clients have to attach to their requests when asking the AS for tokens. This parameter represents the URL of the MCP server the client wants to talk to, and it’s computed by the client from the server URL. The bad MCP server can’t influence the client to use anything else in the resource parameter other than its own URL.

This means the AS can not only show customers exactly which service they’re granting access to (like https://travei.example.com, which sneakily swapped a letter), but also apply a bunch of other policy checks or controls, such as verifying whether the resource has been pre-authorized with a given client.

Even if a user somehow gets fooled into proceeding, the resulting token will only work with the malicious server itself and can’t be used to access any legitimate services, since those servers will reject tokens that weren’t specifically issued for them (more on this shortly).

Mole looking through a lens.

Hold on, did I see that right that this depends on the authorization server (AS) properly supporting the RFC, and while the client can attach the request, it’s entirely possible that the AS will do nothing with it and still return a token?

Unfortunately, at this time this is an accurate statement - using resource is essentially a “best-effort” mitigation. If the AS does not support it, it will ignore it and still return the token; however, the MCP Steering Committee is actively engaging with the developers across some of the most popular Identity Providers, like Okta, Entra ID, and AWS, to ensure that there is a path forward for this RFC to be integrated into the stack.

The flow #

The sequence diagram below outlines the high-level flow. As you can see, there is not a lot of deviation from the current specification - the burden on resource interpretation falls on the AS, which needs to ensure that the value is valid.

%%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#1f1f1f', 'primaryTextColor': '#ffffff', 'primaryBorderColor': '#9333ea', 'lineColor': '#ffffff', 'noteBorderColor': 'rgba(129, 140, 248, 1)', 'noteTextColor': '#ffffff', 'noteBkgColor': '#1f1f1f' }}}%% sequenceDiagram participant Client as MCP Client participant AuthServer as Authorization Server participant MCPServer as MCP Server Note over Client,MCPServer: 1. Discovery Phase Client->>MCPServer: Initial request to protected MCP server MCPServer->>Client: 401 Unauthorized + WWW-Authenticate header Client->>MCPServer: GET /.well-known/oauth-protected-resource MCPServer->>Client: Return PRM document Note over Client,MCPServer: 2. Authorization Phase Client->>AuthServer: Authorization request + resource=https://mcp.example.com AuthServer->>Client: Authorization code Client->>AuthServer: Token request + resource=https://mcp.example.com AuthServer->>Client: Access token (bound to resource) Note over Client,MCPServer: 3. Resource Access Phase Client->>MCPServer: Request + Authorization: Bearer MCPServer->>MCPServer: Validate token audience matches self MCPServer->>Client: MCP server response Note over Client,MCPServer: Security Boundary Enforced rect rgb(143, 2, 2) Client->>MCPServer: Token intended for different resource MCPServer->>Client: 401 Unauthorized (audience mismatch) end

What you need to know as an implemented #

Depending on which part of the MCP interaction you’re responsible for, you might need to take different strategies.

If you’re building an MCP client:

  • You must include the resource parameter representing the connected MCP server URL in both your authorization and token requests
  • Use the proper canonical URI of the MCP server you want to talk to
  • Never reuse tokens between different servers

If you’re building an MCP server:

  • You must check that incoming tokens were actually issued for it specifically
  • Reject any tokens that don’t have the right audience - be strict about this

For additional guidelines, we’re maintaining a separate document that will help you navigate potential threats and mitigation strategies.

Why this matters #

Here’s the thing - making RFC 8707 mandatory isn’t just about fixing today’s problems. It’s about setting MCP up for success as it grows and gains more traction.

This change is especially important if you’re dealing with:

  • Big company deployments where you might have multiple MCP servers running in the same network
  • Multi-tenant setups where keeping different users’ tokens separate is critical
  • Cross-organization scenarios where MCP servers from different companies need to work together

I’ll also mention that the MCP team is really thinking about security from the ground up. As AI agents become more common and start handling more sensitive tasks, having rock-solid authorization is going to be essential.

Conclusion #

If you’re working with MCP authorization, here’s what you need to remember: resource indicators aren’t optional anymore. They’re a core security feature that you need to implement correctly if you want your MCP clients to be secure.

A bit more work will be needed to make this mechanism even more robust, as suggested by Karl McGuinness and Jared Hanson, but we’re going to incrementally improve the core spec as standards evolve.