Contenido del curso

Características Adicionales y Herramientas

Autenticación con cookies en Next.js

Resumen

Implementar autenticación con cookies en Next.js te permite compartir información entre el navegador y el servidor de forma segura, algo que localStorage y sessionStorage no pueden hacer. Aquí aprenderás a crear sesiones, proteger contraseñas con hash y manejar estados de carga y error en el formulario.

Por qué usar cookies en lugar de localStorage o sessionStorage

Las cookies viajan entre cliente y servidor en cada petición, lo que las convierte en la pieza clave para sistemas de autenticación. Esa propiedad es justo lo que diferencia este enfoque de otros mecanismos de almacenamiento del navegador.

En el flujo que construimos, si la cookie existe, el usuario accede a contenido privilegiado. Si no, el middleware lo redirige al login. Esa decisión de redirección ya estaba lista desde la clase anterior, pero quedó pendiente un detalle: al leer la cookie en el middleware, se estaba pasando un string en lugar de la variable real con el nombre de la cookie. Corregir ese typo es el primer paso para que todo funcione [02:00].

¿Qué diferencia hay entre cookies y localStorage? Las cookies se envían automáticamente al servidor en cada request, mientras que localStorage y sessionStorage viven solo en el navegador. Por eso las cookies son la opción natural para autenticación.

Cómo proteger el secreto con un hash SHA256

Guardar la frase "Nunca pares de aprender" en texto plano dentro del código sería un error fatal, sobre todo si ese código termina en Git. La solución es usar un hash, un sistema de encriptación de un solo sentido: dado el resultado, es prácticamente imposible reconstruir la palabra original.

El flujo dentro de la función login queda así:

  • Generar un ID random para el usuario, ya que no hay base de datos real.
  • Importar crypto desde Node.js y crear un hash con algoritmo SHA256.
  • Tomar el password que llega desde el cliente y aplicarle el mismo hash.
  • Comparar el resultado contra el secreto almacenado.

Si los hash no coinciden, la función retorna un objeto con la forma { error: "contraseña incorrecta" }. Si coinciden, se llama a createSession con el ID del usuario y se ejecuta un redirect desde next/navigation hacia la ruta protegida /auth [05:30].

Cómo se crea la sesión y la cookie en el servidor

La utilidad createSession vive en un archivo aparte para mantener el código modular. Ahí dentro se accede a las cookies del servidor usando la API de Next.js:

js import { cookies } from 'next/headers'

export async function createSession(userId) { const expires = Date.now() + 7 * 24 * 60 * 60 * 1000 const cookieStore = await cookies() cookieStore.set(cookieName, userId, { httpOnly: true, secure: true, sameSite: 'lax', path: '/', expires, }) }

La expiración se calcula en milisegundos para siete días. Las opciones httpOnly, secure, sameSite y path no son aleatorias: cada una cumple un rol de seguridad que se profundiza más adelante en el curso [08:45].

Cómo manejar errores y estados de carga con useActionState y useFormStatus

El formulario de login es un componente de React que usa server actions. La acción login se importa directamente y se conecta al formulario, pero en lugar de pasarla cruda, conviene envolverla con useActionState para capturar errores.

useActionState recibe la acción y un estado inicial, y devuelve un array de dos posiciones: el estado actual (con el error si lo hay) y la acción que se le pasa al <form>. Gracias a TypeScript, el tipo del estado se infiere automáticamente desde lo que retorna login, así que state.error queda tipado como string sin esfuerzo extra.

Con ese estado puedes:

  • Activar la prop isInvalid del FormControl de Chakra para pintar el campo en rojo.
  • Mostrar un componente de alerta cuando state.error tenga valor.
  • Reutilizar el mismo objeto de error que devuelve la server action.

¿Para qué sirve useFormStatus? Es un hook de react-dom que te da información del envío del formulario, como si está en pending, la data enviada o el método. Sirve para deshabilitar el botón mientras la acción se ejecuta en el servidor.

useFormStatus se usa dentro de un componente hijo del formulario y no recibe argumentos: React ya conoce internamente qué acción se está ejecutando. Con la propiedad pending puedes deshabilitar el botón de envío y evitar que el usuario haga doble clic mientras la petición viaja al servidor [12:20].

Qué pasa cuando el password es incorrecto

Al probar con cualquier texto distinto al secreto, el formulario muestra la alerta con el mensaje "contraseña incorrecta" como feedback visual. Al ingresar la frase correcta, la cookie se crea, el redirect dispara y el usuario llega a la página protegida con el mensaje "Felicidades, ahora puedes ver el contenido".

¿Es seguro este sistema para producción? No lo es tal cual, pero refleja la base real: nunca almacenes contraseñas en texto plano, guarda solo el hash y compara hashes al hacer login. Los sistemas reales suman salt, rotación de claves y más capas.

La autenticación queda funcionando con middlewares, cookies, server actions y hashing, todo apoyado en las APIs nativas de Next.js y JavaScript. ¿Qué enfoques agregarías tú para llevarlo a un nivel de producción? Déjame tus ideas en los comentarios.