Maximiliano Delgado
npm install --save @nestjs/jwt passport-jwt
npm install --save-dev @types/passport-jwt
¿Por qué implementar JSON Web Tokens (JWT) en nuestra API?
Implementar JSON Web Tokens es esencial para el manejo de la autenticación en APIs. Esta técnica permite que, una vez que el usuario haya iniciado sesión correctamente, se genere un token que le permita enviar solicitudes futuras. Los JWT son fundamentales para API porque transportan información encriptada que puede incluir, por ejemplo, el identificador del usuario y su rol. Además, los JWT ofrecen beneficios adicionales, como la posibilidad de ser utilizados en aplicaciones móviles Android e iOS, superando las limitaciones de cookies y sesiones que funcionan solo en navegadores.
¿Cómo instalar las dependencias necesarias para JWT?
Para trabajar con JWT en NestJS, primero necesitamos instalar algunas dependencias. Estas incluyen tanto las de uso general como las de tipado, que son exclusivamente para el desarrollo:
npm install @nestjs/jwt
npm install --save-dev @types/express
Una vez instaladas, podemos proceder al desarrollo del servicio que gestionará nuestros JWT.
¿Cómo implementar el servicio de JSON Web Tokens?
La implementación del servicio JWT en nuestro sistema requiere unos pocos pasos específicos. Aquí, exploramos cómo hacerlo:
¿Cómo integrar JWT Service en el código?
Importar la librería JWT de NestJS:
import { JwtService } from '@nestjs/jwt';
Inyectar el servicio JWT en nuestro servicio de autenticación:
constructor(private readonly jwtService: JwtService) {}
¿Cómo generar un JWT?
Creamos un método dentro de nuestro servicio de autenticación que genere el token una vez que el usuario haya iniciado sesión correctamente:
import { User } from '../path/to/user.entity'; function generateJWT(user: User) { const payload = { role: user.role, sub: user.id }; return { accessToken: this.jwtService.sign(payload), user, }; }
¿Cómo tipar el payload del JWT?
Definir un payload tipado es esencial para manejar correctamente la información dentro del token:
interface PayloadToken { role: string; sub: number; }
¡Importante! ¿Cómo configurar la firma del JWT?
Finalmente, la firma del JWT necesita configurarse correctamente para garantizar la seguridad:
JwtModule.register({ secret: 'mi_llave_secreta', signOptions: { expiresIn: '60s' }, });
Con esto, está configurado el método para generar un JWT. Sin embargo, en la siguiente clase veremos cómo integrar el JWT Module en el módulo de autenticación y cómo definir la llave secreta correctamente.
Maximiliano Delgado
npm install --save @nestjs/jwt passport-jwt
npm install --save-dev @types/passport-jwt
Carmelo Buelvas Comas
Para MongoDB viene desde la base de datos misma _id por tanto para que obtengamos el sub correctamente debemos colocarlo tal como viene de la base de datos.
generateJWT(user: User) { const payload: PayloadToken = { role: user.role, sub: user._id }; return { access_token: this.jwtService.sign(payload), user, }; }
Manuel Alejandro Blanco Lamas
Para verificar los JWT token generados, pueden utilizar esta herramienta:
Andrés Esteban Rodríguez Jiménez
Carmelo Buelvas Comas
Jose Ripoll Solanes
Hola! Para quitar el __V yo lo he hecho desde
@Schema({ versionKey: false, timestamps: true})
timestamps son el createdAt y updatedAt automáticos por mongodb. Después el id lo creo de forma virtual haciendo una copia de _id
UserSchema.virtual('id').get(function () { return this._id.toHexString(); }); UserSchema.set('toJSON', { virtuals: true });
David Hilera
Si antes de pasar a la siguiente clase tienen un error es por que en la siguiente clase lo resuelven.
Daniel Alejandro Barrientos Quispe
No olviden cambiar el Http code: 200 OK
auth.controller.ts
import { Controller, Post, Req, UseGuards, HttpCode } from '@nestjs/common'; import { Request } from 'express'; import { AuthGuard } from '@nestjs/passport'; @Controller('/auth') export class AuthController { @UseGuards(AuthGuard('local')) @Post('/login') @HttpCode(200) login(@Req() req: Request) { return req.user; } }
Naldo Duran
👏
Conectando Passport con JWT
Los JWT nos permiten tener una verificación de que un usuario se a loggeado en la aplicación de manera satisfactoria, validando en nuestra base de datos y si el usuario es correcto, este token actúa como sesión que permite entrar a los Endpoints que deseamos, y con este token le damos permisos al usuario para hacer request.
Los JWT también sirven en aplicaciones móviles.
Nest.js también tiene un paquete para manejar los JWT, veamos que dependencias debemos instalar para manejar JWT con Nest y Passport:
# dependencias npm install --save @nestjs/jwt passport-jwt # tipos para desarrollo npm install --save-dev @types/passport-jwt
Una vez hecho esto, vamos a ir a nuestro servicio de autenticación para pedirle que cuando un usuario haga loggin, genere un JWT.
**src/auth/service/auth.service.ts**:@Injectable() export class AuthService { async generateJwt(user: User) { const payload = { role: user.role, sub: user.id, }; // ... } }
Bien, ahora, como buena práctica deberíamos crear un modelo del payload que estamos retornando, esto en caso de que necesitemos reutilizarlo en nuestra aplicación:
**src/auth/models/token.model.ts**:// exportamos una interfaz que sea lo que esperamos de el token export interface PayloadToken { role: string; sub: string; }
Y luego, lo que nos quedaría sería importar el modelo utilizarlo:
**src/auth/service/auth.service.ts**:import { PayloadToken } from '../models/token.model'; @Injectable() export class AuthService { async generateJwt(user: User) { const payload: PayloadToken = { role: user.role, sub: user.id, }; // ... } }
Y listo, de esta forma ya tenemos la configuración inicial para crear los JWT.
Para quitar __v y reemplazar _id por id
@Schema() class User extends Document { @Prop({ required: true, unique: true }) email: string; @Prop({ required: true }) password: string; @Prop({ required: true }) role: string; } const UserSchema = SchemaFactory.createForClass(User); UserSchema.method('toJSON', function () { const { __v, _id, password, ...object } = this.toObject(); object.id = _id; return object; }); export { User, UserSchema };