Supabase y Astro
Supabase es un alternativa de código abierto a Firebase. Proporciona una base de datos Postgres, autenticación, funciones edge, suscripciones en tiempo real y almacenamiento.
Inicializando Supabase en Astro
Sección titulada Inicializando Supabase en AstroPrerrequisitos
Sección titulada Prerrequisitos- Un proyecto con Supabase. Si no tienes uno, puedes registrarte gratis en supabase.com y crear un nuevo proyecto.
- Un proyecto de Astro con renderizado del lado del servidor (SSR) habilitado.
- Las credenciales de Supabase para tu proyecto. Puedes encontrarlas en la pestaña Settings > API de tu proyecto de Supabase.
SUPABASE_URL
: La URL de tu proyecto de Supabase.SUPABASE_ANON_KEY
: La clave anónima de tu proyecto de Supabase.
Agregar credenciales de Supabase
Sección titulada Agregar credenciales de SupabasePara agregar tus credenciales de Supabase a tu proyecto de Astro, agrega lo siguiente a tu archivo .env
:
SUPABASE_URL=YOUR_SUPABASE_URLSUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY
Ahora, estas variables de entorno están disponibles en tu proyecto.
Si deseas tener IntelliSense para tus variables de entorno, edita o crea el archivo env.d.ts
en tu directorio src/
y agrega lo siguiente:
interface ImportMetaEnv { readonly SUPABASE_URL: string readonly SUPABASE_ANON_KEY: string}
interface ImportMeta { readonly env: ImportMetaEnv}
Lee más sobre variables de entorno y archivos .env
en Astro.
Tu proyecto debería incluir estos archivos:
Directorysrc/
- env.d.ts
- .env
- astro.config.mjs
- package.json
Instalar dependencias
Sección titulada Instalar dependenciasPara conectarte a Supabase, necesitarás instalar @supabase/supabase-js
en tu proyecto.
npm install @supabase/supabase-js
pnpm add @supabase/supabase-js
yarn add @supabase/supabase-js
Luego, crea un directorio llamado lib
en tu directorio src/
. Aquí es donde agregarás tu cliente de Supabase.
En supabase.ts
, agrega lo siguiente para inicializar tu cliente de Supabase:
import { createClient } from "@supabase/supabase-js";
export const supabase = createClient( import.meta.env.SUPABASE_URL, import.meta.env.SUPABASE_ANON_KEY,);
Ahora, tu proyecto debería incluir estos archivos:
Directorysrc/
Directorylib/
- supabase.ts
- env.d.ts
- .env
- astro.config.mjs
- package.json
Agregar autenticación con Supabase
Sección titulada Agregar autenticación con SupabaseSupabase proporciona autenticación de forma inmediata. Admite autenticación por correo electrónico/contraseña y autenticación OAuth con muchos proveedores, incluidos GitHub, Google y otros.
Prerrequisitos
Sección titulada Prerrequisitos- Un proyecto de Astro inicializado con Supabase.
- Un proyecto de Supabase con autenticación por correo electrónico/contraseña habilitada. Puedes habilitar esto en la pestaña Authentication > Providers de tu proyecto de Supabase.
Creando endpoints de servidor de autenticación
Sección titulada Creando endpoints de servidor de autenticaciónPara agregar autenticación a tu proyecto, deberás crear algunos endpoints de servidor. Estos endpoints se utilizarán para registrar, iniciar sesión y cerrar sesión de los usuarios.
POST /api/auth/register
: para registrar un nuevo usuario.POST /api/auth/signin
: para iniciar sesión de un usuario.GET /api/auth/signout
: para cerrar la sesión de un usuario.
Crea estos endpoints en el directorio src/pages/api/auth
de tu proyecto. Ahora tu proyecto debería incluir estos archivos:
Directorysrc/
Directorylib/
- supabase.ts
Directorypages/
Directoryapi/
Directoryauth/
- signin.ts
- signout.ts
- register.ts
- env.d.ts
- .env
- astro.config.mjs
- package.json
El archivo register.ts
crea un nuevo usuario en Supabase. Acepta una solicitud POST
con un correo electrónico y una contraseña. Luego, utiliza el SDK de Supabase para crear un nuevo usuario.
import type { APIRoute } from "astro";import { supabase } from "../../../lib/supabase";
export const POST: APIRoute = async ({ request, redirect }) => { const formData = await request.formData(); const email = formData.get("email")?.toString(); const password = formData.get("password")?.toString();
if (!email || !password) { return new Response("Correo electrónico y contraseña obligatorios", { status: 400 }); }
const { error } = await supabase.auth.signUp({ email, password, });
if (error) { return new Response(error.message, { status: 500 }); }
return redirect("/signin");};
El archivo signin.ts
inicia sesión de un usuario. Acepta una solicitud POST
con un correo electrónico y una contraseña. Luego, utiliza el SDK de Supabase para iniciar sesión del usuario.
import type { APIRoute } from "astro";import { supabase } from "../../../lib/supabase";
export const POST: APIRoute = async ({ request, cookies, redirect }) => { const formData = await request.formData(); const email = formData.get("email")?.toString(); const password = formData.get("password")?.toString();
if (!email || !password) { return new Response("Correo electrónico y contraseña obligatorios", { status: 400 }); }
const { data, error } = await supabase.auth.signInWithPassword({ email, password, });
if (error) { return new Response(error.message, { status: 500 }); }
const { access_token, refresh_token } = data.session; cookies.set("sb-access-token", access_token, { path: "/", }); cookies.set("sb-refresh-token", refresh_token, { path: "/", }); return redirect("/dashboard");};
El archivo signout.ts
cierra la sesión de un usuario. Acepta una solicitud GET
y elimina los tokens de acceso y actualización del usuario.
import type { APIRoute } from "astro";
export const GET: APIRoute = async ({ cookies, redirect }) => { cookies.delete("sb-access-token", { path: "/" }); cookies.delete("sb-refresh-token", { path: "/" }); return redirect("/signin");};
Crear páginas de autenticación
Sección titulada Crear páginas de autenticaciónAhora que has creado tus endpoints de servidor, crea las páginas que los utilizarán.
src/pages/register
: contiene un formulario para registrar un nuevo usuario.src/pages/signin
: contiene un formulario para iniciar sesión de un usuario.src/pages/dashboard
: contiene una página que solo es accesible para usuarios autenticados.
Crea estas páginas en el directorio src/pages
. Ahora tu proyecto debería incluir estos archivos:
Directorysrc/
Directorylib/
- supabase.ts
Directorypages/
Directoryapi/
Directoryauth/
- signin.ts
- signout.ts
- register.ts
- register.astro
- signin.astro
- dashboard.astro
- env.d.ts
- .env
- astro.config.mjs
- package.json
El archivo register.astro
contiene un formulario para registrar un nuevo usuario. Acepta un correo electrónico y una contraseña y envía una solicitud POST
a /api/auth/register
.
---import Layout from "../layouts/Layout.astro";---
<Layout title="Registrarse"> <h1>Registrarse</h1> <p>¿Ya tienes una cuenta? <a href="/signin">Iniciar sesión</a></p> <form action="/api/auth/register" method="post"> <label for="email" for="email">Correo electrónico</label> <input type="email" name="email" id="email" /> <label for="password">Contraseña</label> <input type="password" name="password" id="password" /> <button type="submit">Iniciar sesión</button> </form></Layout>
El archivo signin.astro
contiene un formulario para iniciar sesión de un usuario. Acepta un correo electrónico y una contraseña y envía una solicitud POST
a /api/auth/signin
. También verifica la presencia de los tokens de acceso y actualización. Si están presentes, redirige al panel.
---import Layout from "../layouts/Layout.astro";
const { cookies, redirect } = Astro;
const accessToken = cookies.get("sb-access-token");const refreshToken = cookies.get("sb-refresh-token");
if (accessToken && refreshToken) { return redirect("/dashboard");}---
<Layout title="Iniciar sesión"> <h1>Iniciar sesión</h1> <p>¿Nuevo aquí? <a href="/register">Crea una cuenta</a></p> <form action="/api/auth/signin" method="post"> <label for="email" for="email">Correo electrónico</label> <input type="email" name="email" id="email" /> <label for="password">Contraseña</label> <input type="password" name="password" id="password" /> <button type="submit">Iniciar sesión</button> </form></Layout>
El archivo dashboard.astro
contiene una página que solo es accesible para usuarios autenticados. Verifica la presencia de los tokens de acceso y actualización. Si no están presentes, redirige a la página de inicio de sesión.
---import Layout from "../layouts/Layout.astro";import { supabase } from "../lib/supabase";
const { cookies, redirect } = Astro;
const accessToken = cookies.get("sb-access-token");const refreshToken = cookies.get("sb-refresh-token");
if (!accessToken || !refreshToken) { return redirect("/signin");}
const { data, error } = await supabase.auth.setSession({ refresh_token: refreshToken.value, access_token: accessToken.value,});
if (error) { cookies.delete("sb-access-token", { path: "/", }); cookies.delete("sb-refresh-token", { path: "/", });
return redirect("/signin");}
const email = data?.user?.email;---<Layout title="panel de control"> <h1>Bienvenido {email}</h1> <p>Estamos felices de verte aquí</p> <form action="/api/auth/signout"> <button type="submit">Cerrar sesión</button> </form></Layout>
Agregar autenticación OAuth
Sección titulada Agregar autenticación OAuthPara agregar autenticación con OAuth a tu proyecto, deberás editar tu cliente de Supabase para habilitar el flujo de autenticación con "pkce"
. Puedes leer más sobre los flujos de autenticación en la documentación de Supabase.
import { createClient } from "@supabase/supabase-js";
export const supabase = createClient( import.meta.env.SUPABASE_URL, import.meta.env.SUPABASE_ANON_KEY, { auth: { flowType: "pkce", }, },);
Luego, en el panel de Supabase, habilita el proveedor de OAuth que te gustaría usar. Puedes encontrar la lista de proveedores compatibles en la pestaña Authentication > Providers de tu proyecto de Supabase.
El siguiente ejemplo utiliza GitHub como proveedor de OAuth. Para conectar tu proyecto a GitHub, sigue los pasos en la documentación de Supabase.
Luego, crea un nuevo endpoint de servidor para manejar la devolución de llamada de OAuth en src/pages/api/auth/callback.ts
. Este endpoint se utilizará para intercambiar el código de OAuth por un token de acceso y actualización.
import type { APIRoute } from "astro";import { supabase } from "../../../lib/supabase";
export const GET: APIRoute = async ({ url, cookies, redirect }) => { const authCode = url.searchParams.get("code");
if (!authCode) { return new Response("No se proporcionó ningún código", { status: 400 }); }
const { data, error } = await supabase.auth.exchangeCodeForSession(authCode);
if (error) { return new Response(error.message, { status: 500 }); }
const { access_token, refresh_token } = data.session;
cookies.set("sb-access-token", access_token, { path: "/", }); cookies.set("sb-refresh-token", refresh_token, { path: "/", });
return redirect("/dashboard");};
Después, edita la página de inicio de sesión para incluir un nuevo botón para iniciar sesión con el proveedor de OAuth. Este botón debe enviar una solicitud POST
a /api/auth/signin
con el provider
establecido en el nombre del proveedor de OAuth.
---import Layout from "../layouts/Layout.astro";
const { cookies, redirect } = Astro;
const accessToken = cookies.get("sb-access-token");const refreshToken = cookies.get("sb-refresh-token");
if (accessToken && refreshToken) { return redirect("/dashboard");}---
<Layout title="Inicia sesión"> <h1>Inicia sesión</h1> <p>¿Nuevo aquí? <a href="/register">Crea una cuenta</a></p> <form action="/api/auth/signin" method="post"> <label for="email" for="email">Correo electrónico</label> <input type="email" name="email" id="email" /> <label for="password">Contraseña</label> <input type="password" name="password" id="password" /> <button type="submit">Iniciar sesión</button> <button value="github" name="provider" type="submit">Inicia sesión con Github</button> </form></Layout>
Finalmente, edita el endpoint del servidor de inicio de sesión para manejar el proveedor de OAuth. Si el provider
está presente, redirigirá al proveedor de OAuth. De lo contrario, iniciará sesión del usuario con el correo electrónico y la contraseña.
import type { APIRoute } from "astro";import { supabase } from "../../../lib/supabase";import type { Provider } from "@supabase/supabase-js";
export const POST: APIRoute = async ({ request, cookies, redirect }) => { const formData = await request.formData(); const email = formData.get("email")?.toString(); const password = formData.get("password")?.toString(); const provider = formData.get("provider")?.toString();
const validProviders = ["google", "github", "discord"];
if (provider && validProviders.includes(provider)) { const { data, error } = await supabase.auth.signInWithOAuth({ provider: provider as Provider, options: { redirectTo: "http://localhost:4321/api/auth/callback" }, });
if (error) { return new Response(error.message, { status: 500 }); }
return redirect(data.url); }
if (!email || !password) { return new Response("Correo electrónico y contraseña obligatorios", { status: 400 }); }
const { data, error } = await supabase.auth.signInWithPassword({ email, password, });
if (error) { return new Response(error.message, { status: 500 }); }
const { access_token, refresh_token } = data.session; cookies.set("sb-access-token", access_token, { path: "/", }); cookies.set("sb-refresh-token", refresh_token, { path: "/", }); return redirect("/dashboard");};
Después de crear el endpoint de devolución de llamada de OAuth y editar la página de inicio de sesión y el endpoint del servidor, tu proyecto debería tener la siguiente estructura de archivos:
Directorysrc/
Directorylib/
- supabase.ts
Directorypages/
Directoryapi/
Directoryauth/
- signin.ts
- signout.ts
- register.ts
- callback.ts
- register.astro
- signin.astro
- dashboard.astro
- env.d.ts
- .env
- astro.config.mjs
- package.json
Recursos de la comunidad
Sección titulada Recursos de la comunidad- Adentrarse en el espíritu navideño con Astro, React y Supabase
- Demo de autenticación con Astro y Supabase