Home > Enterprise >  JwtStrategy requires a secret or key
JwtStrategy requires a secret or key

Time:02-28

I have the following error and I don't know why it happens. Could you help me

ERROR [ExceptionHandler] JwtStrategy requires a secret or key TypeError: JwtStrategy requires a secret or key at new JwtStrategy (C:\Users\wapg2\OneDrive\Productos\node_modules\passport-jwt\lib\strategy.js:45:15)

Auth controler:

import { Controller, Get, Post, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';

import { User, Auth } from 'src/common/decorators';
import { Usuario } from 'src/usuarios/entities';
import { AuthService } from './auth.service';
import { JwtAuthGuard, LocalAuthGuard } from './guards';

@ApiTags('Auth routes')
@Controller('auth')
export class AuthController {
  constructor(private readonly authService: AuthService) {}
  @UseGuards(LocalAuthGuard) //Aca usamos las estrategias
  @Post('login')
  //Passport crea automáticamente un objeto user, según el valor que devolvemos del método validate(), y lo asigna al objeto Request como req.user
  login(@User() usuario: Usuario) {
    const data = this.authService.login(usuario);
    return {
      message: 'Login exitoso',
      data,
    };
  }

  //Esta ruta se vuelve privada al usar JwtAuthGuard
  @UseGuards(JwtAuthGuard)
  @ApiBearerAuth()
  @Get('profile')
  profile(@User() usuario: Usuario) {
    return {
      message: 'Petición correcta',
      usuario,
    };
  }

  @Auth() //-> decorador creado por nosotros para reducir @UseGuards(JwtAuthGuard) y @ApiBearerAuth()
  @Get('refresh')
  refreshToken(@User() usuario: Usuario) {
    const data = this.authService.login(usuario);
    return {
      message: 'Refresh exitoso',
      data,
    };
  }
}

Auth Service

import { Injectable } from '@nestjs/common';
import { compare } from 'bcryptjs';
import { JwtService } from '@nestjs/jwt';

import { Usuario } from 'src/usuarios/entities';
import { UsuariosService } from 'src/usuarios/usuarios.service';
import { response } from 'express';

@Injectable()
export class AuthService {
  constructor(
    //Inyectamos UsuariosService y JwtService para usar las funciones que ofrecen. Estos servicios los podemos usar gracias a que hemos inyectado los módulos UserModule y JwtModule en el AuthModule. Tambien es posible usar el servicio UsuariosService gracias a que hemos exportado dicho servicio en el UsuariosModule (exports: [UsuariosService])
    private readonly usuarioService: UsuariosService,
    private readonly jwtService: JwtService,
  ) {}

  async validateUser(email: string, password: string): Promise<any> {
    const usuario = await this.usuarioService.buscarPorEmail({ email });

    console.log(usuario);

    if (usuario && (await compare(password, usuario.contrasena))) {
      const { contrasena, ...usuarioSinContrasena } = usuario;
      return usuarioSinContrasena;
    }

    return null;
  }

  //login crea el token JWT
  login(usuario: Usuario) {
    const { id } = usuario; //destructuración del objet user. Sacamos el id del retsto de los datos del user (...rest)

    //creamos la info del payload del jwt. el sub va a servir para identificar a cada usuario
    const payload = { sub: id };

    return {
      usuario,
      accesToken: this.jwtService.sign(payload), //Generamos el token
    };
  }
}

Auth Module:

import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { JwtModule } from '@nestjs/jwt';
import { ConfigService } from '@nestjs/config';

import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { JwtStrategy, LocalStrategy } from './strategies';
import { JWT_SECRET } from '../config/constants';
import { UsuariosModule } from 'src/usuarios/usuarios.module';

@Module({
  imports: [
    PassportModule.register({
      defaultStrategy: 'jwt',
    }),
    JwtModule.registerAsync({
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        secret: config.get<string>(JWT_SECRET),
        signOptions: { expiresIn: '60m' }, //Tiempo en el que expira el token
      }),
    }),
    UsuariosModule,
  ], //<-- se inportan los servicios y todo lo que se necesita de passport
  providers: [AuthService, LocalStrategy, JwtStrategy],
  controllers: [AuthController],
})
export class AuthModule {}

Here is my jwtStrtegy

import { ConfigService } from '@nestjs/config';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy, ExtractJwt } from "passport-jwt";
import { JWT_SECRET } from "src/config/constants";
import { UserService } from "src/user/user.service";
import { Injectable } from '@nestjs/common';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy){
  constructor(
    private readonly userService: UserService,
    private readonly config: ConfigService,
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: config.get<string>(JWT_SECRET),
    });
  }

  async validate(payload: any) {
    const { sub: id } = payload;
    return await this.userService.getOne(id);
  }
}

CodePudding user response:

for passport-jwt package option secretOrKey is required the documentation about this:

  • secretOrKey is a string or buffer containing the secret (symmetric) or PEM-encoded public key (asymmetric) for verifying the token's signature.

You can see configure reference at README file of Github repository.

A sample config use a arbitrary value as secretOrKey with:

var opts = {}
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = 'secret'; // arbitrary value used for verify JWT token
opts.issuer = 'accounts.examplesoft.com';
opts.audience = 'yoursite.net';

Sorry for my poor English. It's not my native language.

CodePudding user response:

With nestjs you can create your own strategy file as jwt.stategy.ts

import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import {Request} from 'express';


@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy, "jwt") {
  constructor(configService: ConfigService) {
    super({
      // get JWT from Header 
      // jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      
      // get JWT from cookie
      jwtFromRequest: ExtractJwt.fromExtractors([
        (request: Request) => (
          request.cookies.jwt
        )
      ]),
      ignoreExpiration: false,
      secretOrKey: configService.get<string>("JWT_SECRET"), // REQUIRED
    });
  }

  async validate(payload: any) {
    return payload;
  }
}

And use guard as @UseGuards(AuthGuard("jwt"))

  @UseGuards(AuthGuard("jwt"))
  @ApiBearerAuth()
  @Get('profile')
  profile(@User() usuario: Usuario) {
    return {
      message: 'Petición correcta',
      usuario,
    };
  }

The name "jwt" is a reference to strategy name at definition:

PassportStrategy(Strategy, "jwt")

  • Related