From 462d8c0223e7ee65ee1bc7b4b4fa5bd87e021f9a Mon Sep 17 00:00:00 2001 From: Chris Farhood Date: Mon, 6 Jul 2026 16:53:06 -0400 Subject: [PATCH] auth: implement /consent auto-approve (Claude sends prompt=consent, forcing it) Google login worked; the flow died on the unimplemented consent page. Auto-accept via auth.api.oauth2Consent with the signed oauth_query + session, then 302 to the client callback with the code. --- src/server.ts | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/server.ts b/src/server.ts index 1767f53..bd77b85 100644 --- a/src/server.ts +++ b/src/server.ts @@ -43,6 +43,38 @@ async function startLogin(req: IncomingMessage, res: ServerResponse, rawSearch: } } +// Better Auth redirects here when the client sends prompt=consent (which forces +// the consent screen even with skipConsent). For a personal MCP connector the +// login *is* the authorization, so auto-approve: call the consent endpoint with +// the signed oauth_query + the user's session, then 302 to the client callback. +async function handleConsent(req: IncomingMessage, res: ServerResponse, rawSearch: string) { + const headers = new Headers(); + if (req.headers.cookie) headers.set("cookie", req.headers.cookie); + const oauthQuery = rawSearch.startsWith("?") ? rawSearch.slice(1) : rawSearch; + try { + const result = await auth.api.oauth2Consent({ + body: { accept: true, oauth_query: oauthQuery }, + headers, + returnHeaders: true, + }); + const setCookie = result.headers.getSetCookie(); + if (setCookie.length) res.setHeader("set-cookie", setCookie); + const target = (result.response as { url?: string } | null)?.url; + if (!target) { + res.writeHead(500, { "content-type": "text/plain" }); + res.end("Consent failed."); + return; + } + res.writeHead(302, { location: target }); + res.end(); + } catch (err) { + // eslint-disable-next-line no-console + console.error("[consent] oauth2Consent failed", err); + res.writeHead(500, { "content-type": "text/plain" }); + res.end("Consent error."); + } +} + const server = createServer((req, res) => { const url = new URL(req.url ?? "/", "http://localhost"); if (url.pathname !== "/healthz") { @@ -60,6 +92,10 @@ const server = createServer((req, res) => { void startLogin(req, res, url.search); return; } + if (url.pathname === "/consent" && req.method === "GET") { + void handleConsent(req, res, url.search); + return; + } // Everything else -> Better Auth (async handler). void handler(req, res); });