Contenido del curso

Fundamentos y Primer CRUD

Base de Datos y Persistencia con TypeORM

Rutas protegidas con JWT en NestJS

Resumen

Aprende a proteger rutas en NestJS usando JWT y Passport para que solo usuarios autenticados puedan crear, modificar o eliminar recursos en tu API. Esta guía es para desarrolladores backend que ya implementaron login con access token y necesitan asegurar sus endpoints con autorización por Bearer token.

Después de generar el token en el login, falta el paso clave: usarlo como llave de acceso. Aquí entra en juego una strategy de JWT junto con un guard que valida la firma del token en cada petición.

¿Cómo se envía un JWT en los headers de una petición?

El token viaja dentro del header Authorization siguiendo el protocolo Bearer. La sintaxis es estricta y cualquier error rompe la autenticación.

¿Qué formato debe tener el header Authorization? Debe ser exactamente Bearer seguido de un solo espacio y luego el token. Ni dos espacios, ni minúsculas: Bearer eyJhbGciOi....

En Postman lo configuras eligiendo el tipo Bearer Token y pegando el access token que devolvió el endpoint de login [4:30]. En aplicaciones web suele guardarse en cookies, session storage o local storage; en móviles, dentro de la sesión persistente del dispositivo.

¿Cómo crear una JWT strategy en NestJS?

La estrategia es una clase que extiende de PassportStrategy y le dice a tu aplicación cómo extraer y validar el token. Se construye con tres piezas: el método de extracción, el secreto y un método validate.

¿Qué hace cada parte de la strategy?

  • jwtFromRequest: extrae el token desde el header como Bearer token usando ExtractJwt.fromAuthHeaderAsBearerToken().
  • secretOrKey: recibe el secreto con el que se firmó el token, el mismo que usaste al generarlo en el login.
  • validate(payload): recibe el payload decodificado y devuelve la información que quedará disponible en el request.

El nombre de la strategy importa. Igual que la estrategia local llevaba un identificador, aquí le pasas jwt para luego referenciarla desde el guard [2:45].

¿Cómo inyectar el secreto desde variables de ambiente?

El secreto nunca debe estar hardcodeado. Se inyecta con ConfigService desde @nestjs/config, tipado con tu archivo env.model. Si la variable JWT_SECRET viene undefined, lanzas un throw para evitar que el servidor arranque sin un secreto válido.

typescript constructor(configService: ConfigService<Env>) { const secret = configService.get('JWT_SECRET'); if (!secret) throw new Error('JWT secret is not defined'); super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), secretOrKey: secret, }); }

En validate recuperas la información del payload. Como al firmar guardaste la ID dentro de sub, aquí haces el camino inverso: return { userId: payload.sub }. Eso queda disponible en el request para los siguientes handlers.

¿Cómo proteger endpoints con el guard de JWT?

Una vez registrada la strategy en los providers del módulo, la usas con el decorador @UseGuards(AuthGuard('jwt')) sobre el método del controller que quieras proteger.

¿Qué pasa si no envío el token o lo modifico? El servidor responde con un error de Unauthorized. La firma se valida contra el secreto del servidor, así que cualquier alteración invalida el token automáticamente [6:50].

El nombre 'jwt' que pasas al AuthGuard debe coincidir con el que definiste al crear la strategy. Si no coincide, NestJS no encuentra la estrategia y falla.

¿Cuándo proteger un endpoint y cuándo todo el controller?

La decisión depende de la lógica de negocio. Tienes dos opciones según el alcance que necesites:

  1. Guard a nivel de método: protege solo endpoints específicos como create, update o delete. Útil cuando la lectura es pública.
  2. Guard a nivel de controller: lo declaras una sola vez arriba del @Controller() y aplica a todos los métodos.
  3. Guard global: si toda tu API requiere autenticación, lo registras una vez y te ahorras repetirlo.

Un ejemplo típico: en un módulo de posts dejas findAll y findOne públicos para que cualquiera pueda leer, pero create, update y delete quedan protegidos con el guard de JWT.

¿Cómo se ve el flujo completo en Postman?

Antes de proteger el endpoint, podías crear un post sin enviar nada. Después de aplicar el guard, esa misma petición devuelve Unauthorized [5:20]. Para que funcione, copias el access_token que devolvió el login, lo pegas en la pestaña Authorization como Bearer Token, y reenvías la petición.

Postman además te permite generar el código en distintos lenguajes desde el botón Code: cURL, Dart para Flutter, PHP, Python. En todos verás la misma estructura: header Authorization: Bearer <token> más el body de la petición.

Esa es la base de un sistema de sesiones moderno con tokens: tu frontend o app móvil almacena el token de forma segura y lo adjunta en cada request que necesite autorización. ¿Vas a aplicar el guard endpoint por endpoint o lo pondrás a nivel global en tu próxima API?