Implementa el flujo completo de OAuth social de Medusa para el storefront: boton "Continuar con Google" en account-dialog, ruta proxy que arranca el flujo (GET /api/customer/google/start) y pagina de callback en /auth/google/callback (coincide con GOOGLE_CALLBACK_URL del secret) que resuelve el code/state contra el backend, decodifica el JWT para distinguir cliente nuevo vs existente, crea el customer si hace falta y refresca el token a sesion final -- mismo patron de store/customer-store.ts que login/register por email. Flujo verificado en vivo contra el backend ya desplegado (GET /auth/customer/google, /auth/customer/google/callback con state invalido, /auth/token/refresh con bearer invalido) antes de escribir el codigo, no solo contra la documentacion.
45 lines
1.4 KiB
TypeScript
45 lines
1.4 KiB
TypeScript
"use client";
|
|
|
|
import { useRouter, useSearchParams } from "next/navigation";
|
|
import { useEffect, useRef, useState } from "react";
|
|
import { useCustomerStore } from "@/store/customer-store";
|
|
|
|
export function GoogleCallbackClient() {
|
|
const router = useRouter();
|
|
const searchParams = useSearchParams();
|
|
const loginWithGoogle = useCustomerStore((state) => state.loginWithGoogle);
|
|
const [error, setError] = useState<string | null>(null);
|
|
const ran = useRef(false);
|
|
|
|
useEffect(() => {
|
|
// Guard contra el doble-mount de StrictMode -- el code de Google es
|
|
// de un solo uso, un segundo intento con el mismo code fallaria.
|
|
if (ran.current) return;
|
|
ran.current = true;
|
|
|
|
const code = searchParams.get("code");
|
|
const state = searchParams.get("state");
|
|
if (!code || !state) {
|
|
setError("Faltan parámetros de Google en la URL de retorno.");
|
|
return;
|
|
}
|
|
|
|
loginWithGoogle(code, state).then((ok) => {
|
|
router.replace(ok ? "/" : "/?googleAuthError=1");
|
|
});
|
|
}, [searchParams, loginWithGoogle, router]);
|
|
|
|
return (
|
|
<div className="flex min-h-[60vh] flex-col items-center justify-center gap-3 text-center">
|
|
{error ? (
|
|
<>
|
|
<p className="text-lg font-black text-rose-600">No se pudo iniciar sesión con Google</p>
|
|
<p className="text-sm text-slate-600">{error}</p>
|
|
</>
|
|
) : (
|
|
<p className="text-sm font-bold text-slate-600">Conectando con Google…</p>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|