Cuando un usuario inicia sesión correctamente, el servidor necesita una forma de reconocerlo en todas las solicitudes posteriores sin pedir credenciales cada vez. Aquí es donde entra JSON Web Token (JWT), un mecanismo que genera una credencial temporal con información del usuario, una firma secreta y un tiempo de expiración. Implementarlo en una API con Node.js y Express resulta sencillo con la librería jsonwebtoken de NPM.
¿Cómo funciona JWT con la analogía del hotel?
La forma más clara de entender JWT es con una analogía práctica [0:24]. Imagina que llegas a un hotel, te registras en recepción y te entregan una tarjeta de acceso. Esa tarjeta tiene datos sobre ti: quién eres, a qué habitación puedes acceder y por cuántos días es válida. No necesitas volver a registrarte cada vez que entras al edificio; simplemente presentas la tarjeta.
Si intentas usar esa tarjeta una semana después de tu checkout, el cerrojo la rechazará porque ha expirado. El JWT funciona exactamente igual:
- Contiene un payload con información del usuario (por ejemplo, su ID).
- Tiene una expiración definida al momento de crearlo.
- Se valida con un secret, una cadena secreta que solo el servidor conoce.
¿Cómo instalar y crear un servicio de autenticación con JWT?
El primer paso es instalar la librería desde la terminal [2:41]:
bash
npm install jsonwebtoken --save
Para mantener el código reutilizable, se crea un servicio en lugar de escribir la lógica directamente en cada controlador. Los servicios viven en una carpeta services dentro de api y permiten compartir funcionalidades grandes entre múltiples controladores [3:08].
Dentro de authenticationService.js se define lo siguiente [3:38]:
javascript
const jwt = require('jsonwebtoken');
const secret = 'cadenaRandomDificilDePredecir123!';
const jwtIssuer = (payload, expiresIn) => {
return jwt.sign(payload, secret, { expiresIn });
};
const jwtVerify = (token) => {
return jwt.verify(token, secret);
};
module.exports = { jwtIssuer, jwtVerify };
¿Qué hace cada método del servicio?
- jwtIssuer: es el "recepcionista" que genera la tarjeta. Recibe un payload (datos del usuario) y un tiempo de expiración. Internamente usa
jwt.sign para firmar el token con el secret [4:18].
- jwtVerify: es el "cerrojo" que valida la tarjeta. Recibe el token y comprueba que fue firmado con el mismo secret [5:16].
Un detalle importante: el secret debe permanecer constante. Si se cambia, todos los tokens generados con el valor anterior dejarán de ser válidos al intentar verificarlos [5:36].
¿Cómo se integra JWT en el controlador de login?
En el archivo userController.js, después de que bcrypt confirma que la contraseña es correcta, ya no se devuelve el objeto completo del usuario. En su lugar, se genera un token y se retorna como respuesta [6:16]:
javascript
const token = authenticationService.jwtIssuer(
{ user: user.id },
'1d'
);
return res.status(200).json({ token });
El valor '1d' indica que el token expira en un día. Al probar el endpoint de login en Postman, la respuesta ya no contiene datos del usuario, sino una cadena larga que representa el JWT [7:24].
¿Por qué separar la autenticación en un servicio reutilizable?
Sin un servicio dedicado, habría que duplicar la lógica de generación y verificación de tokens en cada controlador que requiera autenticación, como el de rides o cualquier otro recurso protegido. Al encapsular ambos métodos en authenticationService.js, cualquier controlador puede importarlos y usarlos directamente [3:14].
Este token será la pieza clave para autenticar llamadas posteriores a la API. Cada solicitud a un recurso protegido deberá incluir el JWT, y el servidor lo verificará antes de conceder acceso, exactamente como la tarjeta del hotel abre solo tu habitación y solo durante tu estancia.
¿Tienes dudas sobre cómo validar el token en las rutas protegidas? Comparte tu experiencia en los comentarios.