Trabajo con tokens JWT en TypeScript: librería jsonwebtoken y guía completa

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Tokens JWT en TypeScript: guía completa con la librería jsonwebtoken

\n\n

JSON Web Token (JWT) es un estándar abierto (RFC 7519) para crear tokens de acceso basados en el formato JSON. JWT se utiliza ampliamente para la autenticación y el intercambio de información entre el cliente y el servidor. En TypeScript, gracias al tipado estricto, trabajar con JWT se vuelve especialmente cómodo y seguro. En este artículo, veremos cómo usar la popular librería jsonwebtoken en TypeScript para crear, verificar y gestionar tokens JWT.

\n\n

Instalación y configuración

\n\n

Para empezar, instalaremos los paquetes necesarios:

\n\n
npm install jsonwebtoken\nnpm install -D @types/jsonwebtoken
\n\n

El primer paquete es la librería en sí, el segundo son los tipos de TypeScript para ella. Después de la instalación, crearemos un archivo jwt.service.ts donde almacenaremos toda la lógica de trabajo con tokens.

\n\n

Creación de un token JWT

\n\n

La función principal de jsonwebtoken es sign(). Veamos su uso con tipado:

\n\n
import jwt from 'jsonwebtoken';\n\ninterface TokenPayload {\n  userId: number;\n  email: string;\n  role: 'user' | 'admin';\n}\n\nconst createAccessToken = (payload: TokenPayload): string => {\n  const secret = process.env.JWT_SECRET || 'default_secret';\n  const options: jwt.SignOptions = {\n    expiresIn: '15m', // el token es válido por 15 minutos\n    algorithm: 'HS256',\n  };\n\n  return jwt.sign(payload, secret, options);\n};
\n\n

Importante: nunca almacene la clave secreta en el código. Use variables de entorno (archivo .env).

\n\n

Verificación y decodificación del token

\n\n

Para verificar la autenticidad del token se utiliza la función verify(). Esta verifica automáticamente la firma y la fecha de caducidad:

\n\n
const verifyToken = (token: string): TokenPayload => {\n  const secret = process.env.JWT_SECRET || 'default_secret';\n\n  try {\n    const decoded = jwt.verify(token, secret) as TokenPayload;\n    return decoded;\n  } catch (error) {\n    if (error instanceof jwt.TokenExpiredError) {\n      throw new Error('El token ha expirado');\n    }\n    if (error instanceof jwt.JsonWebTokenError) {\n      throw new Error('Token inválido');\n    }\n    throw error;\n  }\n};
\n\n

Observe la conversión de tipo as TokenPayload — esto garantiza que TypeScript conozca la estructura de los datos decodificados.

\n\n

Refresh-tokens: extensión de sesión

\n\n

En la práctica, los access-tokens tienen una vida corta (15-30 minutos), por lo que se necesita un mecanismo para renovarlos. Para esto se utiliza un refresh-token con una vida útil más larga:

\n\n
const createRefreshToken = (payload: TokenPayload): string => {\n  const secret = process.env.JWT_REFRESH_SECRET || 'refresh_secret';\n  const options: jwt.SignOptions = {\n    expiresIn: '7d', // una semana\n    algorithm: 'HS256',\n  };\n\n  return jwt.sign(payload, secret, options);\n};\n\nconst refreshAccessToken = (refreshToken: string): string => {\n  const secret = process.env.JWT_REFRESH_SECRET || 'refresh_secret';\n\n  try {\n    const decoded = jwt.verify(refreshToken, secret) as TokenPayload;\n    // Se puede verificar si el refresh-token no ha sido revocado en la base de datos\n    return createAccessToken({\n      userId: decoded.userId,\n      email: decoded.email,\n      role: decoded.role,\n    });\n  } catch {\n    throw new Error('Refresh-token no válido');\n  }\n};
\n\n

Middleware para Express en TypeScript

\n\n

La integración de JWT con Express.js requiere crear un middleware. Aquí está la versión tipada:

\n\n
import { Request, Response, NextFunction } from 'express';\n\ninterface AuthRequest extends Request {\n  user?: TokenPayload;\n}\n\nconst authMiddleware = (req: AuthRequest, res: Response, next: NextFunction) => {\n  const authHeader = req.headers.authorization;\n\n  if (!authHeader || !authHeader.startsWith('Bearer ')) {\n    return res                    

Recommendations