Supabase e Astro
Supabase è un’alternativa open source a Firebase. Fornisce un database Postgres, autenticazione, funzioni edge, sottoscrizioni in tempo reale e archiviazione.
Inizializzazione di Supabase in Astro
Sezione intitolata Inizializzazione di Supabase in AstroPrerequisiti
Sezione intitolata Prerequisiti- Un progetto Supabase. Se non ne hai uno, puoi registrarti gratuitamente su supabase.com e creare un nuovo progetto.
- Un progetto Astro con il rendering lato server (SSR) abilitato.
- Credenziali Supabase per il tuo progetto. Puoi trovarle nella scheda Settings > API del tuo progetto Supabase.
SUPABASE_URL
: L’URL del tuo progetto Supabase.SUPABASE_ANON_KEY
: La chiave anonima per il tuo progetto Supabase.
Aggiunta delle credenziali Supabase
Sezione intitolata Aggiunta delle credenziali SupabasePer aggiungere le tue credenziali Supabase al tuo progetto Astro, aggiungi quanto segue al tuo file .env
:
SUPABASE_URL=YOUR_SUPABASE_URLSUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY
Ora, queste variabili d’ambiente sono disponibili nel tuo progetto.
Se desideri avere IntelliSense per le tue variabili d’ambiente, modifica o crea il file env.d.ts
nella tua directory src/
e aggiungi quanto segue:
interface ImportMetaEnv { readonly SUPABASE_URL: string readonly SUPABASE_ANON_KEY: string}
interface ImportMeta { readonly env: ImportMetaEnv}
Leggi di più sulle variabili d’ambiente e i file .env
in Astro.
Il tuo progetto dovrebbe ora includere questi file:
Directorysrc/
- env.d.ts
- .env
- astro.config.mjs
- package.json
Installazione delle dipendenze
Sezione intitolata Installazione delle dipendenzePer connetterti a Supabase, dovrai installare @supabase/supabase-js
nel tuo progetto.
npm install @supabase/supabase-js
pnpm add @supabase/supabase-js
yarn add @supabase/supabase-js
Successivamente, crea una cartella chiamata lib
nella tua directory src/
. Qui aggiungerai il tuo client Supabase.
In supabase.ts
, aggiungi quanto segue per inizializzare il tuo client Supabase:
import { createClient } from "@supabase/supabase-js";
export const supabase = createClient( import.meta.env.SUPABASE_URL, import.meta.env.SUPABASE_ANON_KEY,);
Ora, il tuo progetto dovrebbe includere questi file:
Directorysrc/
Directorylib/
- supabase.ts
- env.d.ts
- .env
- astro.config.mjs
- package.json
Aggiunta dell’autenticazione con Supabase
Sezione intitolata Aggiunta dell’autenticazione con SupabaseSupabase fornisce l’autenticazione out of the box. Supporta l’autenticazione email/password e l’autenticazione OAuth con molti provider, tra cui GitHub, Google e molti altri.
Prerequisiti
Sezione intitolata Prerequisiti- Un progetto Astro inizializzato con Supabase.
- Un progetto Supabase con l’autenticazione email/password abilitata. Puoi abilitarla nella scheda Authentication > Providers del tuo progetto Supabase.
Creazione degli endpoint server di autenticazione
Sezione intitolata Creazione degli endpoint server di autenticazionePer aggiungere l’autenticazione al tuo progetto, dovrai creare alcuni endpoint server. Questi endpoint verranno utilizzati per registrare, accedere e disconnettere gli utenti.
POST /api/auth/register
: per registrare un nuovo utente.POST /api/auth/signin
: per accedere come utente.GET /api/auth/signout
: per disconnettere un utente.
Crea questi endpoint nella directory src/pages/api/auth
del tuo progetto. Il tuo progetto dovrebbe ora includere questi nuovi file:
Directorysrc/
Directorylib/
- supabase.ts
Directorypages/
Directoryapi/
Directoryauth/
- signin.ts
- signout.ts
- register.ts
- env.d.ts
- .env
- astro.config.mjs
- package.json
register.ts
crea un nuovo utente in Supabase. Accetta una richiesta POST
con un’email e una password. Quindi utilizza l’SDK di Supabase per creare un nuovo utente.
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 e password sono obbligatorie", { status: 400 }); }
const { error } = await supabase.auth.signUp({ email, password, });
if (error) { return new Response(error.message, { status: 500 }); }
return redirect("/signin");};
signin.ts
accede come utente. Accetta una richiesta POST
con un’email e una password. Quindi utilizza l’SDK di Supabase per accedere come utente.
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 e password sono obbligatorie", { 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
disconnette un utente. Accetta una richiesta GET
e rimuove i token di accesso e aggiornamento dell’utente.
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");};
Creazione delle pagine di autenticazione
Sezione intitolata Creazione delle pagine di autenticazioneOra che hai creato i tuoi endpoint server, crea le pagine che li utilizzeranno.
src/pages/register
: contiene un modulo per registrare un nuovo utente.src/pages/signin
: contiene un modulo per accedere come utente.src/pages/dashboard
: contiene una pagina accessibile solo agli utenti autenticati.
Crea queste pagine nella directory src/pages
. Il tuo progetto dovrebbe ora includere questi nuovi file:
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
register.astro
contiene un modulo per registrare un nuovo utente. Accetta un’email e una password e invia una richiesta POST
a /api/auth/register
.
---import Layout from "../layouts/Layout.astro";---
<Layout title="Registrazione"> <h1>Registrazione</h1> <p>Hai già un account? <a href="/signin">Accedi</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">Registrati</button> </form></Layout>
signin.astro
contiene un modulo per accedere come utente. Accetta un’email e una password e invia una richiesta POST
a /api/auth/signin
. Controlla anche la presenza dei token di accesso e aggiornamento. Se sono presenti, reindirizza alla 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="Accedi"> <h1>Accedi</h1> <p>Nuovo qui? <a href="/register">Crea un 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">Accedi</button> </form></Layout>
dashboard.astro
contiene una pagina accessibile solo agli utenti autenticati. Controlla la presenza dei token di accesso e aggiornamento. Se non sono presenti, reindirizza alla pagina di accesso.
---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="Dashboard"> <h1>Benvenuto {email}</h1> <p>Siamo felici di vederti qui</p> <form action="/api/auth/signout"> <button type="submit">Disconnettiti</button> </form></Layout>
Aggiunta dell’autenticazione OAuth
Sezione intitolata Aggiunta dell’autenticazione OAuthPer aggiungere l’autenticazione OAuth al tuo progetto, dovrai modificare il tuo client Supabase per abilitare il flusso di autenticazione con "pkce"
. Puoi leggere di più sui flussi di autenticazione nella documentazione di 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", }, },);
Successivamente, nella dashboard di Supabase, abilita il provider OAuth che desideri utilizzare. Puoi trovare l’elenco dei provider supportati nella scheda Authentication > Providers del tuo progetto Supabase.
L’esempio seguente utilizza GitHub come provider OAuth. Per connettere il tuo progetto a GitHub, segui i passaggi nella documentazione di Supabase.
Quindi, crea un nuovo endpoint server per gestire il callback OAuth in src/pages/api/auth/callback.ts
. Questo endpoint verrà utilizzato per scambiare il codice OAuth con un token di accesso e aggiornamento.
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("Nessun codice fornito", { 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");};
Successivamente, modifica la pagina di accesso per includere un nuovo pulsante per accedere con il provider OAuth. Questo pulsante dovrebbe inviare una richiesta POST
a /api/auth/signin
con il provider
impostato sul nome del provider 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="Accedi"> <h1>Accedi</h1> <p>Nuovo qui? <a href="/register">Crea un 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">Accedi</button> <button value="github" name="provider" type="submit">Accedi con GitHub</button> </form></Layout>
Infine, modifica l’endpoint server di accesso per gestire il provider OAuth. Se il provider
è presente, reindirizzerà al provider OAuth. Altrimenti, accederà all’utente con l’email e la password.
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 e password sono obbligatorie", { 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");};
Dopo aver creato l’endpoint di callback OAuth e modificato la pagina e l’endpoint server di accesso, il tuo progetto dovrebbe avere la seguente struttura di file:
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
Risorse della Comunità
Sezione intitolata Risorse della Comunità- Entrare nello spirito delle feste con Astro, React e Supabase
- Demo di autenticazione con Astro e Supabase