Apoya mi contenido: 

Tabla de contenido

Cómo implementar autenticación con Supabase en aplicaciones React

Supabase ofrece autenticación lista para usar (email/contraseña, magic link, OAuth, OTP) con SDKs simples e integración directa con PostgreSQL y Row Level Security (RLS). En esta guía verás cómo añadir login, registro, sesión persistente y protección de rutas en una app React.


1) Crear el proyecto de Supabase

  1. Entra a Supabase y crea un proyecto.
  2. Copia la Project URL y la anon public key (Settings > API).
  3. Habilita proveedores OAuth si los usarás (Auth > Providers).

2) Preparar React

# Vite + React
npm create vite@latest supa-auth -- --template react-swc
cd supa-auth
npm i @supabase/supabase-js
npm i react-router-dom
npm run dev

3) Configurar el cliente de Supabase

src/lib/supabase.js

import { createClient } from "@supabase/supabase-js";

const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY;

export const supabase = createClient(supabaseUrl, supabaseAnonKey, {
  auth: {
    persistSession: true,           // guarda sesión en localStorage
    autoRefreshToken: true
  }
});

.env.local

VITE_SUPABASE_URL=https://xxxx.supabase.co
VITE_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

4) Contexto de autenticación

src/context/AuthContext.jsx

import { createContext, useContext, useEffect, useState } from "react";
import { supabase } from "../lib/supabase";

const AuthContext = createContext();

export function AuthProvider({ children }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // Sesión al cargar
    supabase.auth.getUser().then(({ data }) => {
      setUser(data.user || null);
      setLoading(false);
    });

    // Escuchar cambios (login/logout/refresh)
    const { data: sub } = supabase.auth.onAuthStateChange((_event, session) => {
      setUser(session?.user ?? null);
    });
    return () => sub.subscription.unsubscribe();
  }, []);

  const value = {
    user,
    loading,
    signInWithEmail: (email, password) => supabase.auth.signInWithPassword({ email, password }),
    signUpWithEmail: (email, password) => supabase.auth.signUp({ email, password }),
    signInWithGoogle: () => supabase.auth.signInWithOAuth({ provider: "google" }),
    signOut: () => supabase.auth.signOut()
  };

  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}

export const useAuth = () => useContext(AuthContext);

5) Rutas y protección de páginas

src/main.jsx

import React from "react";
import { createRoot } from "react-dom/client";
import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom";
import { AuthProvider, useAuth } from "./context/AuthContext.jsx";
import Home from "./pages/Home.jsx";
import Dashboard from "./pages/Dashboard.jsx";
import Auth from "./pages/Auth.jsx";

function PrivateRoute({ children }) {
  const { user, loading } = useAuth();
  if (loading) return <p>Cargando...</p>;
  return user ? children : <Navigate to="/auth" replace />;
}

createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <AuthProvider>
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/auth" element={<Auth />} />
          <Route path="/dashboard" element={
            <PrivateRoute><Dashboard /></PrivateRoute>
          } />
        </Routes>
      </BrowserRouter>
    </AuthProvider>
  </React.StrictMode>
);

6) Pantallas de Auth

src/pages/Auth.jsx

import { useState } from "react";
import { useAuth } from "../context/AuthContext";

export default function Auth() {
  const { signInWithEmail, signUpWithEmail, signInWithGoogle } = useAuth();
  const [form, setForm] = useState({ email: "", password: "" });
  const [mode, setMode] = useState("login");
  const [error, setError] = useState("");

  const onSubmit = async (e) => {
    e.preventDefault();
    setError("");
    const fn = mode === "login" ? signInWithEmail : signUpWithEmail;
    const { error } = await fn(form.email, form.password);
    if (error) setError(error.message);
  };

  return (
    <section>
      <h1>{mode === "login" ? "Iniciar sesión" : "Crear cuenta"}</h1>
      <form onSubmit={onSubmit}>
        <input placeholder="Email" type="email"
               value={form.email} onChange={e => setForm({ ...form, email: e.target.value })} />
        <input placeholder="Contraseña" type="password"
               value={form.password} onChange={e => setForm({ ...form, password: e.target.value })} />
        <button type="submit">Continuar</button>
      </form>
      <button onClick={signInWithGoogle}>Entrar con Google</button>
      {error && <p style={{color: "crimson"}}>{error}</p>}
      <p>
        {mode === "login" ? "¿No tienes cuenta?" : "¿Ya tienes cuenta?"}
        <button onClick={() => setMode(mode === "login" ? "signup" : "login")}>
          {mode === "login" ? "Regístrate" : "Inicia sesión"}
        </button>
      </p>
    </section>
  );
}

7) Uso de la sesión en el panel

src/pages/Dashboard.jsx

import { useAuth } from "../context/AuthContext";

export default function Dashboard() {
  const { user, signOut } = useAuth();
  return (
    <main>
      <h2>Hola, {user?.email}</h2>
      <button onClick={signOut}>Cerrar sesión</button>
    </main>
  );
}

8) Seguridad en la base de datos (RLS)

Activa Row Level Security en la tabla que guarda datos del usuario y crea políticas, por ejemplo para que cada usuario solo vea sus registros:

-- En el SQL editor de Supabase:
alter table profiles enable row level security;

create policy "Solo dueño"
on profiles for select
to authenticated
using ( auth.uid() = user_id );

create policy "Insertar propio perfil"
on profiles for insert
to authenticated
with check ( auth.uid() = user_id );

9) Buenas prácticas

  • Usa persistSession y escucha onAuthStateChange para mantener el estado.
  • Protege rutas críticas con componentes tipo <PrivateRoute/>.
  • Si usas servidores (Next.js), valida el JWT del usuario en el backend cuando corresponda.
  • Define políticas RLS antes de exponer datos en producción.

Conclusión

Con el SDK de Supabase puedes agregar autenticación completa a React en minutos. Aprovecha su soporte de sesiones, OAuth y RLS para construir apps seguras y escalables con mínima fricción.

👉 ¿Quieres que integremos Supabase Auth en tu app React con mejores prácticas de seguridad y DX?
Solicítalo aquí.

¡Comunícate con nosotros!