workers-oauth-provider icon indicating copy to clipboard operation
workers-oauth-provider copied to clipboard

[Issue] Invalid redirect URI. The redirect URI provided does not match any registered URI for this client.

Open alexander-zuev opened this issue 8 months ago • 15 comments

Hey :)

I am trying to set up a remote MCP server and implement authentication logic however, I am running into issues with authenticating clients such as Cursor, Windsurf, PyCharm in production environment.

I'd group the issues into 2 large buckets and provide more details for one of them (since I have them). 1. In production client connection fails with _Invalid redirect URI. The redirect URI provided does not match any registered URI for this client._

This error happens when I try to extract clientInfo from the c.env.OAUTH_PROVIDER.lookupClient()

	try {
		// These provider functions might throw errors, or return null/invalid shapes
		oauthReq = await c.env.OAUTH_PROVIDER.parseAuthRequest(c.req.raw);
		// Only lookup client if clientId seems present
		console.log("[AuthContext] Calling lookupClient with clientId:", oauthReq?.clientId);
		if (oauthReq?.clientId) {
			try {
				clientInfo = await c.env.OAUTH_PROVIDER.lookupClient(oauthReq.clientId);
			} catch (lookupError) {
				console.warn(`[AuthContext] Failed to lookup client ${oauthReq.clientId}:`, lookupError);
				clientInfo = undefined; // Explicitly set to null on lookup failure
			}
		}
		console.debug("[AuthContext] OAuth request lookup result:", oauthReq || "No AuthReq info");
		console.debug("[AuthContext] Client lookup result:", clientInfo || "No client info");
	} catch (error) {
		console.warn("[AuthContext] Error parsing request/client from params:", error); // <<< this line triggers error
	}

I am at a loss because:

  • in local dev -> I can connect to the client through inspector with no problem, clientInfo is properly extracted
  • in production -> I run into this error with no additional context

Am I wrong but my MCP server never sets the redirect URIs so I am not sure how can I address this at all?

2. General instability of connection - I appreciate this is very hard to debug but in general connection stability when connecting to: npx mcp-remote http://localhost:8787/sse or the production domain can be described as - "in 50% of the times it works 30% of the time"

The issue is that when I run local dev server (wrangler dev) and connect to it through the inspector -> it all works fine.

Image Image

As soon as I try to connect from a real client I can not get past the extraction of the clientInfo OR in the rare cases that I do the client lands on "Authentication successful you can close and return to CLI" BUT the client (Cursor) is not connected

Image

Main logic is implemented following the instructions in the readme of this repo + following the spec

Source code for all the authentication logic in the MCP server https://github.com/alexander-zuev/kollektiv-mcp/tree/main/src/web

alexander-zuev avatar May 05 '25 04:05 alexander-zuev

UPD:

  • from the logs I do see that on production there is no call to /register from Cursor (but the issue applies to all clients)
Successfully created tail, expires at 2025-05-05T13:36:31Z
Connected to kollektiv-mcp-prod, waiting for logs...
POST https://mcp.thekollektiv.ai/sse - Ok @ 5/5/2025, 3:36:38 PM
  (warn) OAuth error response: 401 invalid_token - Missing or invalid access token
GET https://mcp.thekollektiv.ai/.well-known/oauth-authorization-server - Ok @ 5/5/2025, 3:36:38 PM
GET https://mcp.thekollektiv.ai/authorize?response_type=code&client_id=nzgaETcS1sfHUUiI&code_challenge=REDACTED&code_challenge_method=S256&redirect_uri=http%3A%2F%2F127.0.0.1%3A3334%2Foauth%2Fcallback - Ok @ 5/5/2025, 3:36:39 PM
  (log) [Router] Request received for GET /authorize
  (log) [Middleware] Running for path: /authorize
  (debug) Connected to Supabase at: https://drmzszdytvvfbcytltsw.supabase.co
  (log) [Middleware] Supabase client created and set in context.
  (log) [GET /authorize] Handling request.
  (log) [AuthContext] Attempting to establish valid auth context...
  (log) [Middleware] getAll cookies invoked.
  (log) [Middleware] getAll cookies invoked.
  (warn) [AuthContext] Error parsing request/client from params: Error: Invalid redirect URI. The redirect URI provided does not match any registered URI for this client.
  (log) [AuthContext] Invalid or incomplete context from parameters, attempting cookie fallback.
  (log) [Cookie] No cookie data provided. Skipping cookie parsing.
  (error) [AuthContext] Failed to establish valid context from parameters or cookie.
  (warn) [GET /authorize] No valid auth context: AuthFlowError: Missing or invalid authorization request details.
  (log) [Middleware] Finished handling path: /authorize

While connecting to a local instance through MCP inspector - there is

[wrangler:inf] GET /sse 401 Unauthorized (6ms)
[Router] Request received for GET /authorize
[Middleware] Running for path: /authorize
Connected to Supabase at: http://127.0.0.1:54321
[wrangler:inf] OPTIONS /.well-known/oauth-authorization-server 204 No Content (2ms)
[wrangler:inf] GET /.well-known/oauth-authorization-server 200 OK (1ms)
[wrangler:inf] OPTIONS /register 204 No Content (2ms)
[Middleware] Supabase client created and set in context.
[GET /authorize] Handling request.
[AuthContext] Attempting to establish valid auth context...
[wrangler:inf] POST /register 201 Created (7ms)
[Middleware] getAll cookies invoked.
[Middleware] getAll cookies invoked.
[AuthContext] Calling lookupClient with clientId: cdoxwegcGdZXwgTq
[AuthContext] Attempting to lookup client info with AuthReq: {
  responseType: 'code',
  clientId: 'cdoxwegcGdZXwgTq',
  redirectUri: 'http://localhost:6274/oauth/callback',
  scope: [],
  state: '',
  codeChallenge: 'K0IW3gcsi3TjAH6ND45ifn2XYmZcvBQdLG6iHzndf0M',
  codeChallengeMethod: 'S256'
}
[AuthContext] Client lookup result: {
  clientId: 'cdoxwegcGdZXwgTq',
  redirectUris: [ 'http://localhost:6274/oauth/callback' ],
  clientName: 'MCP Inspector',
  clientUri: 'https://github.com/modelcontextprotocol/inspector',
  grantTypes: [ 'authorization_code', 'refresh_token' ],
  responseTypes: [ 'code' ],
  registrationDate: 1746430681,
  tokenEndpointAuthMethod: 'none'
}
[AuthContext] Valid context established from parameters.

UPD2: my MCP server is deployed as a Cloudflare worker at https://mcp.thekollektiv.ai I verified that I can connect to it from MCP Inspector but not any MCP client (Cursor, Windsurf, PyCharm etc) - super weird

alexander-zuev avatar May 05 '25 07:05 alexander-zuev

@alexander-zuev I was hitting this error as well when testing my MCP server locally (using wrangler dev). I ended up deleting all the keys in my OAUTH_KV KV, and that error went away.

BrandonNoad avatar May 05 '25 14:05 BrandonNoad

Oh my.... 🤯 this indeed made me go past the the initial issue! Thanks so much for the tip!

I was even able to

  • show login screen
  • give consent
  • but then I am redirected back to the loopback (weirdly in 50% of the times it fails)
Image

last hurdle remains... getting very close. User is authenticated but now I am at a point where the client can not connect (unfortunately Cursor's logs are of no help here): Image

I see from my worker's internal logs that authorization was completed successfully.

Image

alexander-zuev avatar May 05 '25 14:05 alexander-zuev

@BrandonNoad hey, just for my reference - were you able to authenticate in any of MCP clients (Cursor, Windsurf, etc)? I am a the point of dropping auth altogether. None of the clients seem to call POST /register in contrast to MCP Inspector so unless my implementation is wrong it seems they simply do not support Oauth flows just yet

alexander-zuev avatar May 06 '25 12:05 alexander-zuev

I've only tried with Claude Desktop + mcp-remote at this point. It works with both the /sse and /mcp endpoints. They just added remote MCP on their web client, but I think it requires a paid account, which I do not have, so haven't tested it there.

I know VS Code hasn't implemented OAuth yet (https://github.com/microsoft/vscode/issues/247759)

I haven't tried with Cursor or Windsurf either.

BrandonNoad avatar May 06 '25 13:05 BrandonNoad

got it - so at least Claude Desktop is working? for some reason I run into the same issues with it as with Cursor (client is not registering).

Thanks for the info anyway! Will try to debug and hopefully resolve this (if auth is supported)

alexander-zuev avatar May 06 '25 13:05 alexander-zuev

Claude desktop works if you configure your MCP server using https://github.com/geelen/mcp-remote

BrandonNoad avatar May 06 '25 14:05 BrandonNoad

This is gold @BrandonNoad thanks! Never checked the docs on mcp-remote so I see at least:

  • a way to bypass auth and send custom headers (super handy)
  • you are saying auth should work when connecting via mcp-remote

Curiously I am always connecting MCP clients via npx mcp-remote ... will give it a closer look tmr

alexander-zuev avatar May 06 '25 15:05 alexander-zuev

Unfortunately the custom headers don't get passed through to the /authorize request needed for this package

BrandonNoad avatar May 06 '25 15:05 BrandonNoad

Man I am super grateful for your message!

I managed to get it to work with all clients (don't fully understand how and I am afraid to touch it so that it doesn't break).

  1. Cleaned the cache with rm -rf ~/.mcp-auth
  2. Created a new KV and bound it to the worker
  3. Cleaned local browser data

From this point I was able to go through auth flow end to end BUT Cursor was still left on red Came back to it 2 minutes later -> it's now green

Tried with Claude for Desktop -> it worked as well

I am gonna try it again tomorrow and seems like there was something in the mcp-remote / KV / browser cache that was messing with the the flow. Dunno

Image Image

With regards to Headers - I was thinking about this as a complete bypass of auth

  1. Option 1 (ideal) is to support Oauth 2.1
  2. Option 2 (if I have to) is to completely drop it. Sending an API key in headers and intercepting in the fetch handler is one way to do that (I hope). So then I could rely on good ol' api keys until auth is more stable

alexander-zuev avatar May 06 '25 15:05 alexander-zuev

I'm currently using Option 2 until OAuth is supported by more clients

BrandonNoad avatar May 06 '25 16:05 BrandonNoad

Can confirm, I'm having this issue as well.

  • issue happened after adding a valid id value in kv_namespaces, and removing it fixed the issue.
  • request url generated by the OAuth client is http://localhost:8788/authorize?response_type=code&client_id=RandomXYZ&code_challenge=RandomXYZ&code_challenge_method=S256&redirect_uri=http://127.0.0.1:3334/oauth/callback and it is being redirected to this uri instead of the redirect_uri specified in header.
  • it works sometimes (not sure why or how, had it working in cloudflare playground)

nimowiz avatar May 10 '25 10:05 nimowiz

This issue is more severe than expected

  • I tried installing gmail mcp server from composio and this same issue (https://mcp.composio.dev/gmail/handsome-puny-yacht-Zbl0QI)
  • tried installing linear hosted mcp and the same issue.

everything getting redirected to http://127.0.0.1:3334/oauth/callback?code=___________ after auth

nimowiz avatar May 10 '25 16:05 nimowiz

this issue in mcp-remote is similar?

https://github.com/geelen/mcp-remote/issues/61

nimowiz avatar May 10 '25 17:05 nimowiz

https://github.com/cloudflare/workers-oauth-provider/compare/v0.0.6...v0.0.7#diff-091962e336f7a9d204618653017cd7d569e37bcfac5ff5333a8d0cb339b0e520R2331

To me it seems that this broke it, as Cursor sends cursor://.

nklmilojevic avatar Sep 16 '25 15:09 nklmilojevic