Autenticación de Aplicaciones Web usando Passport.js y JWT
Introducción
La seguridad de las aplicaciones web modernas depende de dos procesos fundamentales: autenticación y autorización. En este blog abordaremos cómo implementar ambos procesos de forma segura utilizando Passport.js y JSON Web Tokens (JWT) en aplicaciones Node.js.
Autenticación vs Autorización
La autenticación consiste en verificar la identidad de un usuario, asegurándose de que quien dice ser realmente lo sea. Esto comúnmente implica solicitar un nombre de usuario o correo electrónico y una contraseña. Una vez validadas las credenciales, el usuario puede considerarse autenticado.
Por otro lado, la autorización define qué acciones puede realizar el usuario dentro del sistema, basándose en sus roles o permisos asignados. Un ejemplo clásico sería permitir que un usuario autenticado vea productos, mientras que solo un administrador pueda crearlos o eliminarlos.
JSON Web Token (JWT)
Un JWT (JSON Web Token) es un formato estándar utilizado para enviar información firmada y codificada entre dos partes de forma segura. Generalmente, se usa para autenticar usuarios, autorizar accesos y mantener sesiones sin estado.
Está compuesto por tres partes:
- Header: Tipo de token y algoritmo de firma.
- Payload: Datos o 'claims' del usuario.
- Signature: Firma creada usando una clave secreta conocida solo por el servidor.
- El usuario se autentica (por ejemplo, con email y contraseña).
- El servidor genera un JWT con los datos del usuario.
- El cliente guarda el token en localStorage, sessionStorage o cookies.
- El cliente envía el token en el header Authorization en cada petición futura.
- El servidor verifica la firma del token y permite el acceso.
Un middleware en Node.js y Express permite ejecutar funciones antes de que una solicitud alcance su ruta final. Se puede usar para validar autenticaciones, comprobar permisos y proteger endpoints usando API Keys o JWTs.
Ejemplo básico de middleware para validar autenticación por token JWT:
El hashing convierte contraseñas en valores únicos usando algoritmos como bcrypt. A diferencia de la encriptación, el hashing es unidireccional: no se puede revertir. Esto protege las contraseñas en caso de brechas de seguridad en la base de datos.
Ejemplo de uso de bcrypt para hashear y comparar contraseñas:
Passport.js es un middleware para Node.js que facilita la autenticación con múltiples estrategias como Local, JWT y OAuth (Google, Facebook, etc.). Permite agregar autenticación sin alterar mucho el código existente.
Ejemplo de estrategia local con Passport.js:
Generación y Verificación de JWT
Una vez autenticado el usuario, el servidor genera un JWT y lo entrega al cliente. El cliente lo usa para autenticarse automáticamente en futuras solicitudes, manteniendo así sesiones seguras y sin estado.
Ejemplo de generación de un JWT después de login exitoso:
Ejemplo de verificación de un JWT en una ruta protegida:
Protección de Rutas y Control de Roles
Usando Passport.js y JWT, se protegen rutas sensibles exigiendo tokens válidos. Además, podemos controlar el acceso según los roles de usuario (admin, cliente, vendedor) especificados en el payload del JWT.
Ejemplo de middleware para control de roles:
Uso combinado de autenticación y control de roles:
Manejo de Tokens desde el Cliente
El cliente debe almacenar el JWT en localStorage, sessionStorage o cookies HttpOnly, y enviarlo en el header Authorization en cada petición protegida. También se puede automatizar su envío usando interceptores en frameworks como Angular.
Ejemplo de cómo incluir el token JWT en una petición fetch desde el cliente:
Recuperación de Contraseña (NodeMailer)
NodeMailer es una librería de Node.js que facilita el envío de correos electrónicos. Es fundamental para implementar funcionalidades de recuperación de contraseña mediante enlaces seguros enviados al email del usuario.
Ejemplo básico de envío de correo de recuperación de contraseña usando NodeMailer:
Conclusión
La combinación de Passport.js y JWT proporciona una solución robusta y flexible para la autenticación y autorización en aplicaciones Node.js. Implementar prácticas seguras como el hashing de contraseñas, protección de rutas y control de roles es esencial para proteger datos sensibles y brindar una mejor experiencia de usuario.
¿ Quieres conocer más ?
¡ Agenda una llamada !
¡ Contáctanos en WhatsApp