"use client"; /** * OAuthButtons — "Continue with Google / Facebook" row used above both * LoginForm and SignUpForm. Clicking a button performs a top-level * navigation to the BFF's /oauth//start endpoint, which kicks off * the Authorization Code flow. The BFF handles the round-trip and 302s back * to ${frontend}${next} with the session cookie already set. * * Top-level navigation (not fetch) is intentional: cross-origin redirects * to Google / Facebook can't happen from XHR, and we need the BFF to set * the cookie before the browser lands back on the frontend. */ import { useMemo } from "react"; const BFF_BASE = process.env.NEXT_PUBLIC_BFF_URL || "http://localhost:8080"; // Build-time switch — keep the buttons hidden until the Google + Facebook // OAuth apps clear review. Flip `NEXT_PUBLIC_OAUTH_ENABLED=true` on the // Next.js build (Vercel/Dokploy env vars) once approval lands; no code // change required. Defaults to disabled so prod stays safe by default. const OAUTH_ENABLED = process.env.NEXT_PUBLIC_OAUTH_ENABLED === "true"; type Props = { /** Frontend path to land on after the round-trip. Defaults to /u/me. */ next?: string; /** Whether to render a divider with "or continue with email" below. */ showDivider?: boolean; }; export function OAuthButtons({ next, showDivider = true }: Props) { // Suppress the whole row (no buttons → no "or" divider either) while // the OAuth apps are under review. if (!OAUTH_ENABLED) return null; const startUrl = useMemo( () => (provider: "google" | "facebook") => { const u = new URL(`${BFF_BASE}/api/v1/auth/oauth/${provider}/start`); if (next) u.searchParams.set("next", next); return u.toString(); }, [next], ); return (
Google Facebook
{showDivider ? (
or
) : null}
); } function GoogleIcon({ className }: { className?: string }) { return ( ); } function FacebookIcon({ className }: { className?: string }) { return ( ); }