Introducción a OAuth 2.0 y JWT en TypeScript
\n\nEn el desarrollo web moderno, la autorización segura de usuarios es la base de cualquier aplicación. Los dos estándares más populares — OAuth 2.0 y JWT (JSON Web Token) — permiten implementar un sistema robusto de autenticación y control de acceso. En este artículo, analizaremos cómo combinar estas tecnologías en TypeScript para crear una API segura desde cero.
\n\nEste artículo está dirigido a desarrolladores principiantes que ya están familiarizados con los fundamentos de TypeScript y quieren entender cómo funciona la autorización en la práctica. No profundizaremos en conceptos teóricos complejos, sino que nos centraremos en ejemplos de código concretos.
\n\n¿Qué es OAuth 2.0?
\nOAuth 2.0 es un protocolo de autorización que permite a aplicaciones de terceros obtener acceso limitado a los recursos de un usuario sin compartir su contraseña. Imagine que quiere iniciar sesión en un sitio web a través de Google: no le da al sitio su contraseña de Google, simplemente le permite obtener su correo electrónico y nombre. Eso es OAuth 2.0.
\n\n¿Qué es JWT?
\nJWT (JSON Web Token) es un formato de token compacto y autónomo que contiene toda la información necesaria sobre el usuario en forma cifrada. El token consta de tres partes: encabezado, carga útil (payload) y firma. Gracias a la firma, el servidor puede estar seguro de que el token no ha sido falsificado.
\n\n1. Configuración del proyecto e instalación de dependencias
\n\nPara empezar, crearemos un nuevo proyecto en TypeScript. Abra la terminal y ejecute los siguientes comandos:
\n\nmkdir oauth-jwt-ts\ncd oauth-jwt-ts\nnpm init -y\nnpm install express jsonwebtoken bcrypt dotenv cors\nnpm install -D typescript ts-node @types/express @types/jsonwebtoken @types/bcrypt @types/cors @types/node nodemon\n\nCree el archivo tsconfig.json con la configuración básica:
{\n "compilerOptions": {\n "target": "ES2020",\n "module": "commonjs",\n "outDir": "./dist",\n "rootDir": "./src",\n "strict": true,\n "esModuleInterop": true,\n "skipLibCheck": true,\n "forceConsistentCasingInFileNames": true\n },\n "include": ["src/**/*"],\n "exclude": ["node_modules"]\n}\n\nLa estructura de carpetas se verá así:
\n- \n
src/— código fuente \n src/controllers/— controladores \n src/middleware/— middleware para verificar tokens \n src/models/— modelos de datos \n src/routes/— rutas \n .env— variables de entorno \n
2. Implementación de autenticación básica con JWT
\n\nEmpecemos creando un mecanismo simple de registro e inicio de sesión usando JWT. Crearemos el archivo src/config.ts para almacenar las constantes:
import dotenv from 'dotenv';\ndotenv.config();\n\nexport const config = {\n jwtSecret: process.env.JWT_SECRET || 'your-secret-key',\n jwtExpiresIn: process.env.JWT_EXPIRES_IN || '15m',\n refreshTokenExpiresIn: process.env.REFRESH_TOKEN_EXPIRES_IN || '7d',\n port: process.env.PORT || 3000\n};\n\nAhora crearemos un middleware para verificar el token JWT. Archivo src/middleware/auth.middleware.ts:
import { Request, Response, NextFunction } from 'express';\nimport jwt from 'jsonwebtoken';\nimport { config } from '../config';\n\nexport interface AuthRequest extends Request {\n user?: { userId: string; email: string };\n}\n\nexport const authenticateToken = (req: AuthRequest, res: Response, next: NextFunction) => {\n const authHeader = req.headers['authorization'];\n const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN\n\n if (!token) {\n return res.status(401).json({ message: 'Token no proporcionado' });\n }\n\n try {\n const decoded = jwt.verify(token, config.jwtSecret) as { userId: string; email: string };\n req.user = decoded;\n next