Autenticación y Patrones de Auth
Rutas protegidas, contexto de auth, manejo de JWT/sesiones y flujos de login en React
Autenticación en React
La autenticación es una parte crítica de la mayoría de las aplicaciones web. React maneja el lado del frontend — formularios de login/registro, almacenamiento de tokens, protección de rutas y gestión de sesiones de usuario. La lógica real de autenticación ocurre en el backend.
🔐 Flujo de Autenticación
- El usuario ingresa credenciales en un formulario de login
- El frontend envía las credenciales a la API del backend
- El backend verifica y devuelve un token (JWT) o establece una cookie de sesión
- El frontend almacena el token y lo incluye en las solicitudes API posteriores
- Las rutas protegidas verifican la autenticación válida antes de renderizar
Construyendo un Auth Context
import { createContext, useContext, useState, useEffect } from 'react';
const AuthContext = createContext(null);
export function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => { checkAuth(); }, []);
async function checkAuth() {
try {
const token = localStorage.getItem('token');
if (!token) { setLoading(false); return; }
const res = await fetch('/api/auth/me', {
headers: { Authorization: `Bearer ${token}` },
});
if (res.ok) setUser(await res.json());
else localStorage.removeItem('token');
} finally {
setLoading(false);
}
}
async function login(email, password) {
const res = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password }),
});
if (!res.ok) throw new Error('Inicio de sesion fallido');
const { user, token } = await res.json();
localStorage.setItem('token', token);
setUser(user);
}
function logout() {
localStorage.removeItem('token');
setUser(null);
}
return (
<AuthContext.Provider value={{ user, loading, login, logout }}>
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
const context = useContext(AuthContext);
if (!context) throw new Error('useAuth debe usarse dentro de AuthProvider');
return context;
}
Rutas Protegidas
import { Navigate, useLocation } from 'react-router-dom';
import { useAuth } from '../context/AuthContext';
export function ProtectedRoute({ children }) {
const { user, loading } = useAuth();
const location = useLocation();
if (loading) return <LoadingSpinner />;
if (!user) return <Navigate to="/login" state={{ from: location }} replace />;
return children;
}
// Protección basada en roles
export function AdminRoute({ children }) {
const { user, loading } = useAuth();
if (loading) return <LoadingSpinner />;
if (!user) return <Navigate to="/login" replace />;
if (user.role !== 'admin') return <Navigate to="/unauthorized" replace />;
return children;
}
// Uso en el router
<Routes>
<Route path="/login" element={<LoginForm />} />
<Route path="/dashboard" element={
<ProtectedRoute><Dashboard /></ProtectedRoute>
} />
<Route path="/admin" element={
<AdminRoute><AdminPanel /></AdminRoute>
} />
</Routes>
Solicitudes API Autenticadas
export async function authFetch(url, options = {}) {
const token = localStorage.getItem('token');
const res = await fetch(url, {
...options,
headers: {
'Content-Type': 'application/json',
...(token && { Authorization: `Bearer ${token}` }),
...options.headers,
},
});
if (res.status === 401) {
localStorage.removeItem('token');
window.location.href = '/login';
throw new Error('Sesion expirada');
}
return res;
}
🔒 Mejores Practicas de Seguridad
- • Nunca almacenes datos sensibles en localStorage en producción — usa cookies httpOnly
- • Siempre valida en el servidor — la auth del frontend es para UX, no seguridad
- • Usa HTTPS para todas las solicitudes API
- • Implementa refresh de tokens — no uses tokens de acceso de larga duración
- • Limpia el estado de auth al cerrar sesión
✅ Librerías de Auth para Producción
- • NextAuth.js / Auth.js — Auth completo para Next.js
- • Firebase Auth — Servicio de auth de Google
- • Supabase Auth — Auth open-source con seguridad a nivel de fila
- • Clerk — Componentes de auth listos para usar
- • Auth0 — Auth empresarial con personalización extensa