Supabase y Astro
Supabase es una alternativa de código abierto a Firebase. Proporciona una base de datos Postgres, autenticación, edge functions, suscripciones en tiempo real y almacenamiento.
Inicializando Supabase en Astro
Sección titulada “Inicializando Supabase en Astro”Requisitos previos
Sección titulada “Requisitos previos”- Un proyecto de Supabase. Si no tienes uno, puedes registrarte de forma gratuita en supabase.com y crear un nuevo proyecto.
- Un proyecto de Astro con
output: 'server'habilitado para renderizado bajo demanda. - Supabase credentials for your project. You can find these in the Settings > API tab of your Supabase project.
SUPABASE_URL: La URL de tu proyecto de Supabase.SUPABASE_ANON_KEY: La clave anónima para tu proyecto de Supabase.
Añadiendo credenciales de Supabase
Sección titulada “Añadiendo credenciales de Supabase”Para añadir tus credenciales de Supabase a tu proyecto de Astro, añade lo siguiente a tu archivo .env:
SUPABASE_URL=YOUR_SUPABASE_URLSUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEYAhora, 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 añade 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 ahora debería incluir estos archivos:
Directoriosrc/
- env.d.ts
- .env
- astro.config.mjs
- package.json
Instalación de dependencias
Sección titulada "Instalación de dependencias"Para conectarte a Supabase, necesitarás instalar @supabase/supabase-js en tu proyecto.
npm install @supabase/supabase-jspnpm add @supabase/supabase-jsyarn add @supabase/supabase-jsA continuación, crea una carpeta llamada lib en tu directorio src/. Aquí es donde añadirás tu cliente de Supabase.
En supabase.ts, añade 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:
Directoriosrc/
Directoriolib/
- supabase.ts
- env.d.ts
- .env
- astro.config.mjs
- package.json
Añadiendo autenticación con Supabase
Sección titulada “Añadiendo autenticación con Supabase”Supabase proporciona autenticación de forma nativa. Admite autenticación de correo electrónico/contraseña y autenticación OAuth con muchos proveedores, incluyendo GitHub, Google y varios otros.
Requisitos previos
Sección titulada “Requisitos previos”- Un proyecto de Astro inicializado con Supabase.
- Un proyecto de Supabase con autenticación de correo/contraseña habilitada. Puedes habilitarla en la pestaña Autenticación > Proveedores de tu proyecto de Supabase.
Creando endpoints de servidor de autenticación
Sección titulada “Creando endpoints de servidor de autenticación”Para añadir autenticación a tu proyecto, necesitarás crear algunos endpoints de servidor. Estos endpoints se usará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 la 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. Si estás utilizando el modo de renderizado estático, debes especificar export const prerender = false en la parte superior de cada archivo para renderizar estos endpoints bajo demanda. Tu proyecto debería incluir ahora estos nuevos archivos:
Directoriosrc/
Directoriolib/
- supabase.ts
Directoriopages/
Directorioapi/
Directorioauth/
- signin.ts
- signout.ts
- register.ts
- env.d.ts
- .env
- astro.config.mjs
- package.json
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.
// With `output: 'static'` configured:// export const prerender = false;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("Email and password are required", { status: 400 }); }
const { error } = await supabase.auth.signUp({ email, password, });
if (error) { return new Response(error.message, { status: 500 }); }
return redirect("/signin");};signin.ts inicia la 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 la sesión del usuario.
// With `output: 'static'` configured:// export const prerender = false;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("Email and password are required", { 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");};signout.ts cierra la sesión de un usuario. Acepta una solicitud GET y elimina los tokens de acceso y actualización del usuario.
// With `output: 'static'` configured:// export const prerender = false;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");};Creando páginas de autenticación
Sección titulada “Creando páginas de autenticación”Ahora que has creado tus endpoints de servidor, crea las páginas que los usarán.
src/pages/register: contiene un formulario para registrar un nuevo usuario.src/pages/signin: contiene un formulario para iniciar la sesión de un usuario.src/pages/dashboard: contiene una página a la que solo pueden acceder los usuarios autenticados.
Crea estas páginas en el directorio src/pages. Tu proyecto debería incluir ahora estos nuevos archivos:
Directoriosrc/
Directoriolib/
- supabase.ts
Directoriopages/
Directorioapi/
Directorioauth/
- signin.ts
- signout.ts
- register.ts
- register.astro
- signin.astro
- dashboard.astro
- env.d.ts
- .env
- astro.config.mjs
- package.json
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="Register"> <h1>Register</h1> <p>Already have an account? <a href="/signin">Sign in</a></p> <form action="/api/auth/register" method="post"> <label for="email">Email</label> <input type="email" name="email" id="email" /> <label for="password">Password</label> <input type="password" name="password" id="password" /> <button type="submit">Register</button> </form></Layout>signin.astro contiene un formulario para iniciar la 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 comprueba la presencia de los tokens de acceso y de actualización. Si están presentes, redirige al panel de control (dashboard).
---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="Sign in"> <h1>Sign in</h1> <p>New here? <a href="/register">Create an account</a></p> <form action="/api/auth/signin" method="post"> <label for="email">Email</label> <input type="email" name="email" id="email" /> <label for="password">Password</label> <input type="password" name="password" id="password" /> <button type="submit">Login</button> </form></Layout>dashboard.astro contiene una página a la que solo pueden acceder los usuarios autenticados. Comprueba la presencia de los tokens de acceso y de actualización. Si no están presentes o no son válidos, redirige a la página de inicio de sesión.
---import Layout from "../layouts/Layout.astro";import { supabase } from "../lib/supabase";
const accessToken = Astro.cookies.get("sb-access-token");const refreshToken = Astro.cookies.get("sb-refresh-token");
if (!accessToken || !refreshToken) { return Astro.redirect("/signin");}
let session;try { session = await supabase.auth.setSession({ refresh_token: refreshToken.value, access_token: accessToken.value, }); if (session.error) { Astro.cookies.delete("sb-access-token", { path: "/", }); Astro.cookies.delete("sb-refresh-token", { path: "/", }); return Astro.redirect("/signin"); }} catch (error) { Astro.cookies.delete("sb-access-token", { path: "/", }); Astro.cookies.delete("sb-refresh-token", { path: "/", }); return Astro.redirect("/signin");}
const email = session.data.user?.email;---<Layout title="dashboard"> <h1>Welcome {email}</h1> <p>We are happy to see you here</p> <form action="/api/auth/signout"> <button type="submit">Sign out</button> </form></Layout>Añadiendo autenticación OAuth
Sección titulada “Añadiendo autenticación OAuth”Para añadir autenticación OAuth a tu proyecto, necesitará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", }, },);A continuación, en el panel de control de Supabase, habilita el proveedor de OAuth que te gustaría usar. Puedes encontrar la lista de proveedores compatibles en la pestaña Autenticación > Proveedores de tu proyecto de Supabase.
El siguiente ejemplo utiliza GitHub como proveedor de OAuth. Para conectar tu proyecto a GitHub, sigue los pasos de la documentación de Supabase.
Luego, crea un nuevo endpoint de servidor para manejar la devolución de llamada (callback) de OAuth en src/pages/api/auth/callback.ts. Este endpoint se usará para intercambiar el código OAuth por un token de acceso y otro de 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 code provided", { 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");};A continuación, 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 con 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="Sign in"> <h1>Sign in</h1> <p>New here? <a href="/register">Create an account</a></p> <form action="/api/auth/signin" method="post"> <label for="email">Email</label> <input type="email" name="email" id="email" /> <label for="password">Password</label> <input type="password" name="password" id="password" /> <button type="submit">Login</button> <button value="github" name="provider" type="submit">Sign in with 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á la 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("Email and password are required", { 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 (callback) 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:
Directoriosrc/
Directoriolib/
- supabase.ts
Directoriopages/
Directorioapi/
Directorioauth/
- 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"- Entrando en el espíritu navideño con Astro, React y Supabase
- Demostración de autenticación con Astro y Supabase