The Auth Section Conflates Two Auth Flows · modelcontextprotocol · Discussion #536

6 min read Original article ↗

Pre-submission Checklist

  • I have verified that this discussion would not be more appropriate as an issue in a specific repository
  • I have searched existing discussions to avoid duplicates

Discussion Topic

tl;dr: in future MCP Host/Server interactions, there will always be two auth flows that overlap. Confusingly, in the updated MCP auth spec, the same actors play distinct auth roles simultaneously in each flow... the spec not only implies these flows are separable (they're not), it doesn't actually elaborate on the most important flow.

Specifically...
The Auth Section of the Spec conflates two overlapping auth flows that need disambiguating.

This will continue to cause confusion and make it hard for devs to adhere to the spec and move up the stack.

While the spec states it does not want to be opinionated, it needs to give a realistic, end-to-end example.

The Setup - My MCP Host and MCP Server

I built a remote, multi-user MCP Host (containing MCP Clients) and an MCP Server. The server accesses the MSFT Graph API to fetch emails and calendar.

My MSFT MCP Server is going to be typical of 90% of worthwhile MCP Servers in that it is accessing private resources.

The spec covers the authorization between my MCP Host/Clients + my MCP Server + use of a 3rd Party Authorization Server (possibly my own).

As you will see, that's only half the picture we need.

The Start of Confusion - Auth Flow 1

The first Auth Flow is actually pretty typical except at the end when you realize the user hasn't gotten access to anything yet.

That requires a second flow that takes place in parallel, with the same actors playing different roles.

For this first flow, the roles run as follows:

Resource Owner: In all scenarios the user plays the role of "Resource Owner".

Unfortunately, the other roles are going to conflate and shift.

Auth Client: When my MCP Host first requests resources, it is acting as the the "Auth Client".

Resource Server: The MCP Server is the "Resource Server."

Confusion Point 1 - what "Resource" does it have? The user's emails? No. That's not this auth flow. It is protecting the MCP Server's endpoints.

Auth Server: To access those endpoints we do an auth flow with a "3rd party Authorization server."

Confusion Point 2 - this authorization server will have nothing to do with what the user wants (i.e. MSFT emails). It might be Auth0 or some local Better Auth maintained by me. It is purely there for MCP Host & Server.

Spec Implies We're Done... We're Not... We're Deeply Not

At the end of this auth flow, the one in the spec, what have we got? Authorized endpoint access. That's it.

In a purist and theoretical sense, we have completed a discrete task of authenticating and authorizing our MCP Host/Client to this MCP Server.

But in 90% of instances, we're not done. We haven't accomplished the entire point of this flow which is to get access to MSFT Graph emails.

Technically we have another, distinct auth flow about to trigger but there are three major problems with where the spec leaves things:

  1. The spec doesn't distinguish adequately between these flows
  2. The spec doesn't elaborate on the second flow
  3. The 3rd parties who do elaborate (mainly Auth0) add to the confusion (see below)

Confusion Compounds - Auth Flow 2

In this new flow, the user wants to access their MSFT emails. This is technically a distinct and new flow but it is also 100% taking place alongside to the previous flow. Watch how the previous roles change.

Resource Owner: The MCP Host now needs to authenticate with MSFT Graph on behalf of the user. The user is still the "Resource Owner".

Resource (changed): The "Resource" they want has now changed from Server Endpoint to what intuitively made sense: MSFT emails.

Client (changed): The MCP Server is now the "Auth Client" on behalf of the user.

Auth Server (changed): The "Auth Server" is no longer my Better Auth Server, it is now MSFT's Auth Server.

Confusion Point 3: When Auth0 docs try to fill the gap in the MCP Spec, they use Auth0 as the example of the Authorization Server. But Auth0 is then also used as the Authorization Server example in the previous section. The confusion being: these are two distinct authorization servers! One is working on behalf of the MCP Server. Protecting a "Resource" we don't even realize is a resource (endpoints). The other Auth server is protecting what we care about: MSFT emails.

Missing The Most Important Link - How To Link Flows

Everything up until now dense, but at least it is familiar.

We have two overlapping and interconnected Auth flows. Fine.

Except, this leaves out the main, unfamiliar step we all need clarity on: in future calls, how do we associate the MCP Host's access tokens (those from the first flow) with MSFT's access tokens (those from the second flow)?

Put more directly: how do we link the user between these?

Here is where the spec breaks down.

One of the purported arguments for separating out the MCP Server into distinct Authorization Servers and Resources Servers was to keep the MCP Stateless.

This is no longer possible here. Because the spec forbits "token in tokens" the MCP Server will have to maintain some persistent storage (imagine a Redis stash).

That also means in Flow 1, a user_id gets saved in the MCP Server that can later be associated with the same user_id in Flow 2. While that is doable, it would help greatly to know where, when, and how that might be done most efficiently.

This Will Become A Big Gap

Is this all just a "skill issue"? In some sense, yes.

But also, we all know auth is complicated. Now we have double auth + unfamiliar linkages that contradict a previously "known" premise (i.e. the idea that MCP Servers might be stateless).

I think the reason this hasn't been discussed more is the two dominant groups of MCP builders don't feel this pain:

  1. Pro shops like Claude and Cursor have auth specialists that can figure this out from first-principles and know what workarounds are valid
  2. Solo builders haven't quite moved this far up the stack nor have they expanded into true multi-user scenarios

The problem is, we solo-builders need to be able to compete with the Cursor's of the world and it's currently very opaque on how to do that.