imansi-auth-react
Hooks de autenticación para React: login, registro, 2FA, OAuth, recuperación de contraseña y gestión de sesiones. Sin componentes visuales. Compatible con
imansi-auth-node.
¿Qué es?
imansi-auth-react es la librería de hooks de autenticación del ecosistema Imansi. No incluye componentes visuales: solo la lógica y el estado. Vos armás la UI como quieras.
Está diseñada para funcionar con imansi-auth-node en el backend.
Se recomienda usar ambas librerías juntas. Comparten el mismo contrato HTTP y los mismos nombres en español.
┌─────────────────────┐ ┌─────────────────────┐
│ imansi-auth-react │ ──────► │ imansi-auth-node │
│ (tu frontend) │ HTTP │ (tu backend) │
└─────────────────────┘ └─────────────────────┘Características
- Hooks específicos para cada flujo: login, registro, 2FA, recuperación y más
- Sin componentes visuales: máxima libertad para diseñar tu UI
- OAuth con GitHub y Google listo para enchufar
- Sesión persistente con cookies httpOnly
- Refresh tokens automáticos sin que el usuario note nada
- Protección de rutas (
<ProtegerRuta>y<RedirigirSiAutenticado>) - 100% configurable desde props y configuración
- JavaScript puro. Sin TypeScript, sin sorpresas
- Cero dependencias de UI. Vos decidís cómo se ve todo
Instalación
npm install imansi-auth-reactRequiere React 18+ y react-router-dom 6+:
npm install react react-dom react-router-domPara el backend (recomendado):
npm install imansi-auth-nodeUso rápido
1. Envolvé tu app con <ProveedorAutenticacion>
// src/App.jsx
import { BrowserRouter } from 'react-router-dom';
import { ProveedorAutenticacion } from 'imansi-auth-react';
const configuracion = {
urlBase: 'http://localhost:3000',
modoAlmacenamiento: 'httpOnly',
incluirCredenciales: true,
rutaLogin: '/login',
rutaTrasLogin: '/panel',
rutaTrasRegistro: '/panel',
};
export default function App() {
return (
<BrowserRouter>
<ProveedorAutenticacion configuracion={configuracion}>
{/* Tu app */}
</ProveedorAutenticacion>
</BrowserRouter>
);
}2. Armá tu propio login con useLogin
import { useState } from 'react';
import { useNavigate, Link } from 'react-router-dom';
import { useLogin } from 'imansi-auth-react';
export function MiLogin() {
const { iniciarSesion, error, requiereVerificacion2fa } = useLogin();
const navegar = useNavigate();
const [correo, setCorreo] = useState('');
const [contrasena, setContrasena] = useState('');
const [enviando, setEnviando] = useState(false);
if (requiereVerificacion2fa) {
return <MiVerificacion2FA />;
}
async function manejar(evento) {
evento.preventDefault();
setEnviando(true);
const resultado = await iniciarSesion({ correo, contrasena });
setEnviando(false);
if (!resultado.ok) {
alert(resultado.error.mensaje);
return;
}
if (resultado.requiere2fa) return;
navegar('/panel');
}
return (
<form onSubmit={manejar}>
<h1>Iniciar sesión</h1>
<input
type="email"
placeholder="Correo"
value={correo}
onChange={(e) => setCorreo(e.target.value)}
/>
<input
type="password"
placeholder="Contraseña"
value={contrasena}
onChange={(e) => setContrasena(e.target.value)}
/>
{error && <p style={{ color: 'red' }}>{error.mensaje}</p>}
<button type="submit" disabled={enviando}>
{enviando ? 'Entrando...' : 'Entrar'}
</button>
<Link to="/recuperar">¿Olvidaste tu contraseña?</Link>
</form>
);
}3. Protegé tus rutas
import { ProtegerRuta, RedirigirSiAutenticado } from 'imansi-auth-react';
<Routes>
<Route
path="/login"
element={
<RedirigirSiAutenticado>
<MiLogin />
</RedirigirSiAutenticado>
}
/>
<Route
path="/panel"
element={
<ProtegerRuta cargando={<p>Cargando...</p>}>
<MiPanel />
</ProtegerRuta>
}
/>
</Routes>Hooks disponibles
useLogin()
Login con email y contraseña.
const { iniciarSesion, cargando, error, requiereVerificacion2fa } = useLogin();
await iniciarSesion({ correo, contrasena });
// → { ok: true, usuario } | { ok: true, requiere2fa: true } | { ok: false, error }useRegistro()
Registro con email, contraseña y nombre opcional.
const { registrarUsuario, error } = useRegistro();
await registrarUsuario({ nombre, correo, contrasena });useVerificar2FA()
Verifica el código de 2FA.
const { verificarDosFactores, reenviarDosFactores, error } = useVerificar2FA();
await verificarDosFactores('353251');
await reenviarDosFactores();useRecuperacion()
Solicitar y restablecer contraseña.
const { solicitarRecuperacion, restablecerContrasena } = useRecuperacion();
await solicitarRecuperacion('usuario@email.com');
await restablecerContrasena({ token, contrasena: 'nueva123' });useCambioContrasena()
Cambiar contraseña estando logueado.
const { cambiarContrasena, usuario } = useCambioContrasena();
if (usuario?.tieneContrasena) {
await cambiarContrasena({ contrasenaActual, contrasenaNueva });
}useEditarPerfil()
Editar el nombre del usuario.
const { editarPerfil, usuario } = useEditarPerfil();
await editarPerfil({ nombre: 'Ivan Mansilla' });useSesiones()
Listar y revocar sesiones activas.
const { listarSesiones, revocarSesion } = useSesiones();
const sesiones = await listarSesiones();
await revocarSesion(sesiones[0].id);useOAuth()
Iniciar el flujo OAuth.
const { iniciarOAuth, proveedores, textos } = useOAuth();
<button onClick={() => iniciarOAuth('github')}>
Continuar con GitHub
</button>useAutenticacion()
Hook completo con todo. Útil si preferís un solo hook.
const {
usuario, token, sesion, autenticado, cargando, error,
iniciarSesion, registrarUsuario, cerrarSesion, recargarUsuario,
idPendiente2fa, requiereVerificacion2fa,
verificarDosFactores, reenviarDosFactores, cancelar2fa,
listarSesiones, revocarSesion,
solicitarRecuperacion, restablecerContrasena,
cambiarContrasena, editarPerfil,
configuracion,
} = useAutenticacion();Protección de rutas
<ProtegerRuta>
Bloquea rutas privadas. Si no hay sesión, redirige al login.
| Prop | Tipo | Descripción |
|---|---|---|
redireccion | string | Ruta a la que redirigir (default: configuracion.rutaLogin) |
cargando | ReactNode | Qué mostrar mientras se valida la sesión |
<RedirigirSiAutenticado>
Para rutas públicas (login, registro). Si ya hay sesión, redirige.
| Prop | Tipo | Descripción |
|---|---|---|
redireccion | string | Ruta a la que redirigir (default: configuracion.rutaTrasLogin) |
cargando | ReactNode | Qué mostrar mientras se valida |
Configuración completa
const configuracion = {
urlBase: 'http://localhost:3000',
modoAlmacenamiento: 'httpOnly',
incluirCredenciales: true,
rutaLogin: '/login',
rutaTrasLogin: '/panel',
rutaTrasRegistro: '/panel',
rutaTrasRestablecer: '/login',
oauth: {
proveedores: ['github', 'google'],
textos: {
github: 'Entrar con GitHub',
google: 'Entrar con Google',
o: 'o también',
},
},
};Seguridad
- Cookies httpOnly: el token nunca es accesible desde JavaScript
- Refresh tokens automáticos: el access token dura poco y se renueva solo
- Detección automática de 401: si el access token expira, el hook lo renueva sin que el usuario note nada
- Deduplicación de refrescos concurrentes: si varias peticiones reciben 401 al mismo tiempo, se hace un solo refresh
- Sin almacenamiento inseguro por defecto: no usamos
localStoragea menos que lo pidas explícitamente
Próximos pasos
- imansi-auth-node — El backend
- @imansi/templates-auth — Componentes visuales listos para usar
- Quickstart — Empezá tu proyecto
