Guía para Implementar JWT en Node.js con NestJS

    Suscríbete y mantente al día con las últimas novedades y tendencias tecnológicas

    ¿Qué es un JSON Web Token?

    El JSON Web Token (JWT) es un estándar abierto (RFC 7519) que define una forma compacta y autónoma de transmitir información de manera segura entre partes como un objeto JSON. Esta información se puede verificar y confiar en ella porque está firmada digitalmente. Los JWT pueden ser firmados usando un secreto (con el algoritmo HMAC) o un par de claves pública/privada utilizando RSA o ECDSA.

    ¿Cuándo deberías usar JSON Web Tokens?

    • Autorización: Este es el escenario más común para usar JWT. Una vez que el usuario ha iniciado sesión, cada solicitud subsiguiente incluirá el JWT, lo que permite al usuario acceder a rutas, servicios y recursos permitidos por ese token. El inicio de sesión único (Single Sign-On) utiliza ampliamente JWT debido a su pequeño tamaño y su capacidad para usarse fácilmente entre diferentes dominios.
    • Intercambio de información: Los JSON Web Tokens son una buena manera de transmitir información de manera segura entre partes. Dado que los JWT pueden estar firmados, por ejemplo, utilizando pares de claves pública/privada, puedes estar seguro de que los remitentes son quienes dicen ser. Además, como la firma se calcula utilizando el encabezado y el cuerpo, también puedes verificar que el contenido no haya sido alterado.

    Configurando el Proyecto

    npm i -g @nestjs/cli
    nest new jwt-auth-demo
    cd jwt-auth-demo

    npm install @nestjs/jwt @nestjs/passport passport passport-jwt bcrypt

    Definir el modelo del usuario:

    // src/auth/user.model.ts
    export class User {
    id: number;
    username: string;
    password: string; // Store hashed passwords
    }

    Crear un servicio de usuario simple:

    // src/auth/auth.service.ts
    import { Injectable } from ‘@nestjs/common’;
    import { User } from ‘./user.model’;
    import * as bcrypt from ‘bcrypt’;

    @Injectable()
    export class AuthService {
    private users: User[] = [];

    async register(username: string, password: string): Promise<User> {
    const hashedPassword = await bcrypt.hash(password, 10);
    const newUser = { id: Date.now(), username, password:

    hashedPassword };
    this.users.push(newUser);
    return newUser;
    }

    async validateUser(username: string, password: string): Promise<any> {
    const user = this.users.find(user => user.username === username);
    if (user && await bcrypt.compare(password, user.password)) {
    return user;
    }
    return null;
    }
    }

    Estrategia JWT

    Decide el tipo de autenticación que deseas implementar. Las opciones comunes incluyen autenticación por nombre de usuario/contraseña, inicio de sesión con redes sociales (por ejemplo, utilizando OAuth) o autenticación basada en tokens (por ejemplo, JWT).

    Configurar JWT:

    // src/auth/auth.module.ts
    import { Module } from ‘@nestjs/common’;
    import { AuthService } from ‘./auth.service’;

    import { JwtModule } from ‘@nestjs/jwt’;
    import { PassportModule } from ‘@nestjs/passport’;
    import { JwtStrategy } from ‘./jwt.strategy’;

    @Module({
    imports: [
    PassportModule,
    JwtModule.register({
    secret: ‘secretKey’, // Use environment variable for production
    signOptions: { expiresIn: ’60s’ },
    }),
    ],
    providers: [AuthService, JwtStrategy],
    exports: [AuthService],
    })
    export class AuthModule {}

    Implementar la estrategia JWT:

    // src/auth/jwt.strategy.ts
    import { Injectable } from ‘@nestjs/common’;
    import { PassportStrategy } from ‘@nestjs/passport’;
    import { ExtractJwt, Strategy } from ‘passport-jwt’;
    import { AuthService } from ‘./auth.service’;

    @Injectable()
    export class JwtStrategy extends PassportStrategy(Strategy) {
    constructor(private authService: AuthService) {
    super({
    jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
    ignoreExpiration: false,
    secretOrKey: ‘secretKey’,
    });
    }

    async validate(payload: any) {
    return this.authService.validateUser(payload.username, payload.sub);
    }
    }

    Creación de EndPoint de autenticación:

    // src/auth/auth.controller.ts
    import { Controller, Post, Body, UseGuards } from ‘@nestjs/common’;
    import { AuthService } from ‘./auth.service’;
    import { JwtService } from ‘@nestjs/jwt’;
    import { LocalAuthGuard } from ‘./local-auth.guard’;

    @Controller(‘auth’)
    export class AuthController {
    constructor(
    private readonly authService: AuthService,
    private jwtService: JwtService,
    ) {}

        @Post(‘register’)
    async register(@Body() body: { username: string; password: string }) {
    return this.authService.register(body.username, body.password);
    }

    @UseGuards(LocalAuthGuard)
       @Post(‘login’)
    async login(@Body() body: { username: string; password: string }) {
    const user = await this.authService.validateUser(body.username, body.password);
    const payload = { username: user.username, sub: user.id };
    return {
    access_token: this.jwtService.sign(payload),
    };
    }
    }

    Implementar  LocalAuthGuard

    // src/auth/local-auth.guard.ts
    import { Injectable } from ‘@nestjs/common’;
    import { AuthGuard } from ‘@nestjs/passport’;

    @Injectable()
    export class LocalAuthGuard extends AuthGuard(‘local’) {}

    Rutas protegidas:

    Usa el decorador @UseGuards para proteger rutas específicas:

    import { Controller, Get, UseGuards } from ‘@nestjs/common’;
    import { JwtAuthGuard } from ‘./jwt-auth.guard’;

    @Controller(‘protected’)
    export class ProtectedController {
    @UseGuards(JwtAuthGuard)
    @Get()
    getProtectedData() {
    return { message: ‘This is protected data’ };
    }
    }

    Conclusión:

    Este artículo cubrió la implementación de la autenticación JWT en una aplicación de Node.js utilizando NestJS. Se destacaron los beneficios clave de JWT para la autenticación de usuarios sin estado y escalable, junto con la configuración de un módulo de autenticación, la implementación de una estrategia JWT y la creación de puntos finales seguros para el registro y el inicio de sesión de usuarios. Para mejorar aún más la seguridad de la aplicación, es recomendable explorar las mejores prácticas relacionadas con la expiración de tokens y los tokens de actualización.

     


     

    En GRUPO EBIM desarrollamos soluciones TI a la medida de las necesidades de tu empresa. Somos expertos en consultoría SAP, Outsourcing de personal TI, y contamos con un equipo de profesionales dispuestos a brindar soluciones digitales escalables para tu negocio. ¡Llena nuestro formulario de contacto y obtén más información sobre los servicios que ofrecemos!

    Suscríbete y mantente al día con las últimas novedades y tendencias tecnológicas

    EBIM

    Escrito por EBIM

    BLOG

    Más Articulos Relacionados

    ¿Qué es el Ciclo de Vida del Desarrollo de Software (SDLC)? 

    ¿Qué son las Pruebas de Software? 

    Cómo elegir una software factory sin equivocarte: guía definitiva para tomar la mejor decisión