import { useState } from "react"; import { Button } from "@executor-js/react/components/button"; // --------------------------------------------------------------------------- // MCP OAuth consent. Better Auth's mcp() plugin redirects /authorize here // (consentPage) with ?consent_code&client_id&scope once the user is signed in; // the self-host serving layer forces it for every client (see // src/auth/force-mcp-consent) and enriches it with the registered client_name // (src/auth/index). We show the requesting client + scopes and require an // explicit Allow/Deny — without this the server would auto-consent, so any // authorize link clicked by a logged-in user would silently mint a token for // whoever crafted it. On a decision we POST /api/auth/oauth2/consent and follow // the returned redirectURI (back to the client's callback with a code, or with // an access_denied error). Rendered directly by routes/__root.tsx (a static // import, not a lazy route — so it can't hit Vite's dynamic-import dep flake), // chromeless inside the auth gate. No throws (result drives state). // --------------------------------------------------------------------------- const SCOPE_LABELS: Record = { openid: "Confirm your identity", profile: "Read your basic profile", email: "Read your email address", offline_access: "Stay connected (refresh access without re-approving)", }; export const McpConsentPage = () => { const params = new URLSearchParams(globalThis.window?.location.search ?? ""); const consentCode = params.get("consent_code") ?? ""; const clientId = params.get("client_id") ?? ""; // The name the client gave at registration (e.g. "Codex"). Self-declared, so // it's shown as a label, not a trust signal — hence the id + warning below. const clientName = params.get("client_name")?.trim() || ""; const scopes = (params.get("scope") ?? "").split(/[+\s]+/).filter(Boolean); const [busy, setBusy] = useState<"allow" | "deny" | null>(null); const [error, setError] = useState(null); const decide = async (accept: boolean) => { setBusy(accept ? "allow" : "deny"); setError(null); const res = await fetch(`${globalThis.location.origin}/api/auth/oauth2/consent`, { method: "POST", headers: { "content-type": "application/json" }, credentials: "include", body: JSON.stringify({ accept, consent_code: consentCode }), }); if (!res.ok) { setBusy(null); setError( "Could not record your decision. The request may have expired — try connecting again.", ); return; } const body = (await res.json()) as { redirectURI?: string }; if (body.redirectURI) { globalThis.location.href = body.redirectURI; return; } setBusy(null); setError("No redirect was returned by the server."); }; return (
); };