JWT + Express paso a paso
Paso 1: instalar
Sección titulada «Paso 1: instalar»pnpm add express jsonwebtokenpnpm add -D @types/jsonwebtokenbun add express jsonwebtokenbun add -d @types/jsonwebtokennpm install express jsonwebtokennpm install -D @types/jsonwebtokenPaso 2: un endpoint que firma un token (sin verificar password todavía, a propósito)
Sección titulada «Paso 2: un endpoint que firma un token (sin verificar password todavía, a propósito)»import express from "express"import jwt from "jsonwebtoken"
const app = express()app.use(express.json())
const SECRET = "solo-para-este-ejemplo-usar-env-var-en-real"
app.post("/token", (req, res) => { const { userId } = req.body const token = jwt.sign({ sub: userId }, SECRET, { expiresIn: "1h" }) res.json({ token })})Paso 3: probar que emite un token
Sección titulada «Paso 3: probar que emite un token»curl -X POST http://localhost:3000/token \ -H "Content-Type: application/json" \ -d '{"userId": "123"}'{ "token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjMi..." }Paso 4: un middleware que verifica el token
Sección titulada «Paso 4: un middleware que verifica el token»function requireAuth( req: express.Request, res: express.Response, next: express.NextFunction) { const token = req.headers.authorization?.replace("Bearer ", "")
if (!token) { return res.status(401).json({ error: "Falta el token" }) }
try { const payload = jwt.verify(token, SECRET) as { sub: string } ;(req as any).userId = payload.sub next() } catch { res.status(401).json({ error: "Token inválido o expirado" }) }}
app.get("/protegida", requireAuth, (req, res) => { res.json({ mensaje: `Hola, usuario ${(req as any).userId}` })})Paso 5: probar la ruta protegida
Sección titulada «Paso 5: probar la ruta protegida»# Sin token: 401curl http://localhost:3000/protegida
# Con token: 200curl http://localhost:3000/protegida \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..."Siguiente paso natural
Sección titulada «Siguiente paso natural»Esta versión firma un token para cualquier userId que le pasen, sin verificar contraseña — es intencional, para aislar el mecanismo de JWT antes de sumar autenticación real. El paso siguiente es Auth completa, que agrega registro, login con bcrypt, y cookies en vez de headers manuales.
Consideraciones
Sección titulada «Consideraciones»SECREThardcodeado en el código es solo para este ejemplo aislado — en cualquier proyecto real va en una variable de entorno, ver Variables de entorno en Node.(req as any).userIdes un atajo rápido para esta demo mínima — la forma correcta de tiparreq.userestá en Middleware de autenticación.