Contenido del curso

Fundamentos y Primer CRUD

Base de Datos y Persistencia con TypeORM

Endpoint de login con Passport en NestJS

Resumen

Implementar el endpoint de login en NestJS es uno de los pasos más críticos al construir un sistema de autenticación, porque define cómo validas credenciales, proteges información sensible y devuelves la sesión correcta al cliente. Aquí verás cómo estructurar ese endpoint usando un controller dedicado, integrarlo con la estrategia local de Passport y probarlo en Postman, todo siguiendo buenas prácticas modulares.

Por qué crear un controller dedicado para autenticación

La documentación oficial sugiere colocar el login dentro del AppController, pero esa no es una buena práctica cuando piensas en mantenibilidad. Lo recomendable es aislar la responsabilidad de autenticación en su propio scope.

Al generar un controller con el mismo nombre del módulo, NestJS lo asocia automáticamente al módulo correcto. En la clase se ejecutó algo así como nest g controller auth, y el CLI lo registró sin esfuerzo extra [01:20].

Una vez creado, conviene moverlo a una carpeta controllers/ dentro de auth/ para mantener limpia la estructura modular. El AuthModule debe quedar con el array de controllers actualizado para que la ruta funcione.

¿Dónde debe ir el endpoint de login en NestJS? Dentro de un controller propio en el módulo auth, no en el AppController. Así mantienes el scope de autenticación separado y escalable.

Cómo conectar el endpoint con la estrategia local de Passport

El corazón del login está en el decorador UseGuards(AuthGuard('local')). Ese guard es un guardián que intercepta la petición y ejecuta la estrategia que definiste previamente en LocalStrategy [02:30].

El nombre 'local' debe coincidir exactamente con el nombre que registraste en tu strategy. Si pones 'local' en un lado y otra cosa en el otro, el guard falla silenciosamente y no entiendes por qué nada funciona.

Las importaciones clave son:

  • AuthGuard desde @nestjs/passport.
  • UseGuards y Post desde @nestjs/common.
  • Request como tipo desde express.
  • El decorador @Req() para acceder al request.

Cuando la estrategia valida correctamente, Passport inyecta el usuario directamente en request.user. Por eso en el handler del login simplemente retornas req.user sin necesidad de lógica extra.

Por qué tipar el request desde Express

NestJS corre por defecto sobre Express, aunque puedes hacer un switch a Fastify si buscas más rendimiento. Mientras uses Express, importa el tipo Request desde 'express' para que TypeScript te dé autocompletado correcto sobre req.user y demás propiedades [04:10].

Cómo probar el endpoint de login en Postman

La prueba se hace contra POST /auth/login enviando un body en formato raw JSON con dos campos: email y password. Recuerda que Passport local por defecto espera username, así que en la estrategia debes configurar usernameField: 'email' para que reconozca tu campo personalizado.

El flujo de pruebas que conviene ejecutar es:

  1. Enviar email correcto con password incorrecto.
  2. Enviar email incorrecto con password correcto.
  3. Enviar ambos campos correctos.

En los dos primeros casos, la respuesta debe ser 401 Unauthorized sin detalles adicionales. En el tercero, recibirás el objeto del usuario validado.

¿Por qué no especificar si falla el email o el password? Porque revelarlo abre la puerta a ataques de fuerza bruta. Si dices "password incorrecto", confirmas indirectamente que el email existe en tu base de datos. Mejor responde un genérico "no autorizado".

En el frontend o app móvil normalmente se muestra un mensaje amigable tipo "verifica tu usuario o contraseña", pero la API nunca debe dar pistas específicas. Es una regla de seguridad casi intuitiva.

Cómo viaja el password de forma segura

Cuando el cliente envía las credenciales, la información viaja por HTTPS, que cifra el contenido en tránsito. El servidor recibe el password en el DTO, pero nunca lo almacena tal cual: ejecuta una comparación contra el hash guardado en la base de datos usando bcrypt o similar [07:45].

Si el hash coincide, Passport considera la autenticación exitosa y devuelve el usuario. Ese usuario queda disponible en request.user y, dependiendo del esquema de sesión, posteriormente generarás un JWT o una cookie de sesión.

¿Qué devuelve el endpoint de login al autenticar correctamente? El objeto del usuario validado, sin el password. Más adelante, ese objeto se usará para firmar un token JWT o crear una cookie de sesión según la estrategia que elijas.

¿Ya tienes tu endpoint de login funcionando? Cuéntame en los comentarios qué estrategia de sesión vas a implementar después: JWT o cookies.