Implementar Autenticación y Gestión de Usuarios

Video
25 min~4 min lectura

Reproductor de video

Concepto clave

La autenticación en GraphQL es el proceso de verificar la identidad de un usuario antes de permitirle acceder a recursos protegidos. A diferencia de REST, donde cada endpoint puede tener su propia lógica de autenticación, en GraphQL manejamos esto a nivel de resolvers o contexto. Piensa en esto como el guardia de seguridad de un edificio: verifica tu identidad una vez (al entrar) y luego decides a qué oficinas (resolvers) puedes acceder.

En nuestro proyecto de red social, necesitamos dos componentes principales: JSON Web Tokens (JWT) para mantener el estado de sesión y bcrypt para encriptar contraseñas. JWT funciona como un pase de acceso temporal que el cliente envía en cada solicitud, similar a una credencial de empleado que muestras al entrar a diferentes áreas. La gestión de usuarios incluye operaciones CRUD (Crear, Leer, Actualizar, Eliminar) pero con capas adicionales de seguridad y validación.

Cómo funciona en la práctica

Vamos a implementar la autenticación paso a paso en nuestro proyecto con Next.js y Apollo Server:

  1. Configuración del esquema GraphQL: Define tipos para User, AuthPayload (que devuelve token y usuario), y mutaciones como register, login, updateUser.
  2. Resolvers protegidos: Implementa middleware en Apollo Server que verifica el token JWT antes de ejecutar resolvers sensibles.
  3. Encriptación de contraseñas: Usa bcrypt para hashear contraseñas antes de guardarlas en la base de datos.
  4. Generación de tokens: Crea JWT al registrar o iniciar sesión, incluyendo el ID de usuario y expiración.

Ejemplo de mutación de registro:

mutation Register($input: RegisterInput!) {
  register(input: $input) {
    token
    user {
      id
      username
    }
  }
}

Caso de estudio

Imagina que estamos construendo el perfil de usuario para nuestra red social. Un usuario quiere actualizar su biografía, pero solo si está autenticado. Implementamos esto con:

  • Un resolver updateUser que verifica el contexto (donde almacenamos el usuario autenticado).
  • Validación de entrada usando GraphQL scalars para tipos personalizados como EmailAddress o NonEmptyString.
  • Actualización en la base de datos solo si el ID del usuario en el token coincide con el ID del perfil a modificar.

Tabla de operaciones de usuario:

OperaciónEndpoint GraphQLAutenticación Requerida
Registromutation registerNo
Loginmutation loginNo
Obtener perfilquery user
Actualizar perfilmutation updateUser
En producción, siempre usa HTTPS para transmitir tokens y considera rate limiting para prevenir ataques de fuerza bruta en login.

Errores comunes

  • Exponer datos sensibles en respuestas GraphQL: Asegúrate de no incluir campos como contraseñas o tokens antiguos en los tipos de usuario. Usa selección de campos explícita.
  • Validación insuficiente en mutaciones: No confíes solo en el cliente; valida entradas en el servidor con librerías como Joi o Validator.js.
  • Almacenar contraseñas en texto plano: Siempre usa bcrypt con salt rounds adecuados (ej., 10-12) para hashear contraseñas.
  • Manejo incorrecto de tokens expirados: Implementa refresh tokens o notifica al cliente cuando el JWT expire, en lugar de dejar al usuario sin acceso abruptamente.
  • Falta de sanitización de inputs: Previene inyecciones SQL o NoSQL limpiando datos antes de procesarlos, especialmente en campos como biografía o nombres.

Checklist de dominio

  • Puedo implementar un sistema de registro y login con JWT en Apollo Server.
  • Sé proteger resolvers específicos verificando autenticación en el contexto.
  • Uso bcrypt para encriptar contraseñas y comparar hashes de forma segura.
  • Manejo errores de autenticación (ej., token inválido) con respuestas GraphQL claras.
  • Valido y sanitizo inputs de usuario en mutaciones.
  • Configuro expiración de tokens y manejo de sesiones.
  • Integro la autenticación con el cliente Next.js, enviando tokens en headers de solicitudes.

Implementa Autenticación JWT en tu API GraphQL

En este ejercicio, extenderás el proyecto de red social para incluir autenticación segura. Sigue estos pasos:

  1. Amplía el esquema GraphQL: Agrega tipos User y AuthPayload, y mutaciones register y login en tu archivo de definiciones GraphQL.
  2. Configura bcrypt y jsonwebtoken: Instala las dependencias necesarias y crea funciones helper para hashear contraseñas y generar/verificar JWT.
  3. Implementa resolvers: En tu archivo de resolvers, crea las funciones para register (valida input, hashea contraseña, guarda usuario, genera token) y login (verifica credenciales, devuelve token).
  4. Protege un resolver: Elige un resolver existente, como getUserProfile, y modifícalo para que verifique autenticación usando el contexto de Apollo Server antes de devolver datos.
  5. Prueba con Apollo Studio: Ejecuta mutaciones de registro y login, luego usa el token en headers para acceder al resolver protegido.

Entrega: Un repositorio Git con los cambios implementados y un README que explique cómo probar la autenticación.

Pistas
  • Usa variables de entorno para almacenar el secreto JWT, nunca lo hardcodees en el código.
  • En el resolver de login, compara la contraseña proporcionada con el hash almacenado usando bcrypt.compare.
  • Para proteger resolvers, accede al usuario desde context.user y verifica si está definido antes de proceder.

Evalua tu comprension

Completa el quiz interactivo de arriba para ganar XP.