From 0b17005949e734e3bbb2cc1853b5217d6e1f028c Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 26 Feb 2026 19:15:16 +0000 Subject: [PATCH 1/2] fix: strip oauth resource in authorize route Co-authored-by: Kent C. Dodds --- epicshop/epic-me/app/routes/oauth/authorize.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/epicshop/epic-me/app/routes/oauth/authorize.tsx b/epicshop/epic-me/app/routes/oauth/authorize.tsx index 82bac67..d5204cd 100644 --- a/epicshop/epic-me/app/routes/oauth/authorize.tsx +++ b/epicshop/epic-me/app/routes/oauth/authorize.tsx @@ -67,9 +67,17 @@ export async function action({ request, context }: Route.ActionArgs) { Object.fromEntries(url.searchParams), ) + // Strip `resource` from the request — the MCP client sends its own URL + // (e.g. http://localhost:56000/mcp) as the resource, but API calls go to + // a different host (the Worker). Storing that as the token audience would + // cause a permanent mismatch on every /db-api call. With no audience set, + // the library skips audience validation entirely. + const { resource: _ignored, ...requestWithoutResource } = requestParams as + typeof requestParams & { resource?: string } + const { redirectTo } = await context.cloudflare.env.OAUTH_PROVIDER.completeAuthorization({ - request: requestParams, + request: requestWithoutResource, userId: String(user.id), metadata: { label: user.email, From 5557ea98cd1d4b15037a06ee12b9a4f76a3fdc8d Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Thu, 26 Feb 2026 15:08:13 -0700 Subject: [PATCH 2/2] fix: ensure original request body is preserved when stripping resource from token request --- epicshop/epic-me/workers/app.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/epicshop/epic-me/workers/app.ts b/epicshop/epic-me/workers/app.ts index 6eaafe5..37d159b 100644 --- a/epicshop/epic-me/workers/app.ts +++ b/epicshop/epic-me/workers/app.ts @@ -50,7 +50,8 @@ async function stripResourceFromTokenRequest(request: Request): Promise const contentType = request.headers.get('content-type') ?? '' if (!contentType.includes('application/x-www-form-urlencoded')) return request - const body = await request.text() + // Read from a clone so the original request body stays available. + const body = await request.clone().text() const params = new URLSearchParams(body) if (!params.has('resource')) return request