最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - secretOrPrivateKey must have a value - NestJs - Stack Overflow

programmeradmin0浏览0评论

I get this error while implementing jwt in my server. I'm using NestJs and I'm following the documentation. I've been looking for solutions about this error here but it seems nothing works. I've stored the secret key in my .env file, add ConfigModule.forRoot() in my app.module, so I can successfully read all my environment variables. This is my code, if someone can point me in the right direction.

app.module.ts

@Module({
  imports: [
    ConfigModule.forRoot(),
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: process.env.DB_HOST,
      port: +process.env.DB_PORT,
      username: process.env.DB_USER,
      password: process.env.DB_PASS,
      database: process.env.DB_NAME,
      entities: ['dist/**/*.entity{.ts,.js}'],
      synchronize: false,
    }),
    UsersModule,
    AuthModule,
    PolsModule,
  ],
  controllers: [UsersController, AuthController, PolsController],
  providers: [UsersService, AuthService, PolsService, JwtService],
})
export class AppModule {}

auth.module.ts

@Module({
  imports: [
    UsersModule,
    PassportModule,
    JwtModule.register({
      secret: process.env.JWT_SECRET_KEY,
      signOptions: { expiresIn: '4h' },
    }),
  ],
  providers: [AuthService, UsersService, LocalStrategy, JwtStrategy],
  controllers: [AuthController],
})
export class AuthModule {}

auth.controller.ts

@Controller('auth')
export class AuthController {
  constructor(
    private authService: AuthService,
    private usersService: UsersService,
  ) {}

  @UseGuards(LocalAuthGuard)
  @Post()
  async login(@Request() req) {
    return this.authService.login(req.user);
  }
}

auth.service.ts

@Injectable()
export class AuthService {
  constructor(
    private usersService: UsersService,
    private jwtService: JwtService,
  ) {}

  async login(user: any) {
    const payload = { username: user.username, sub: user.id };
    console.log(process.env.JWT_SECRET_KEY);
    return {
      access_token: this.jwtService.sign(payload),
    };
  }
}

console error

// console.log(process.env.JWT_SECRET_KEY)
fb8C47vylwS
[Nest] 50225  - 01/07/2022, 17:46:37   ERROR [ExceptionsHandler] secretOrPrivateKey must have a value
Error: secretOrPrivateKey must have a value
    at Object.module.exports [as sign] (/Users/user/dev/backend/pol-api/node_modules/jsonwebtoken/sign.js:107:20)
    at JwtService.sign (/Users/user/dev/backend/pol-api/node_modules/@nestjs/jwt/dist/jwt.service.js:28:20)
    at AuthService.login (/Users/user/dev/backend/pol-api/src/auth/auth.service.ts:26:37)
    at AuthController.login (/Users/user/dev/backend/pol-api/src/auth/auth.controller.ts:29:29)
    at /Users/user/dev/backend/pol-api/node_modules/@nestjs/core/router/router-execution-context.js:38:29
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at /Users/user/dev/backend/pol-api/node_modules/@nestjs/core/router/router-execution-context.js:46:28
    at /Users/user/dev/backend/pol-api/node_modules/@nestjs/core/router/router-proxy.js:9:17

As I said I tried different potential solutions I found in other similar questions, (like this one) but none of the answers worked for me.

I get this error while implementing jwt in my server. I'm using NestJs and I'm following the documentation. I've been looking for solutions about this error here but it seems nothing works. I've stored the secret key in my .env file, add ConfigModule.forRoot() in my app.module, so I can successfully read all my environment variables. This is my code, if someone can point me in the right direction.

app.module.ts

@Module({
  imports: [
    ConfigModule.forRoot(),
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: process.env.DB_HOST,
      port: +process.env.DB_PORT,
      username: process.env.DB_USER,
      password: process.env.DB_PASS,
      database: process.env.DB_NAME,
      entities: ['dist/**/*.entity{.ts,.js}'],
      synchronize: false,
    }),
    UsersModule,
    AuthModule,
    PolsModule,
  ],
  controllers: [UsersController, AuthController, PolsController],
  providers: [UsersService, AuthService, PolsService, JwtService],
})
export class AppModule {}

auth.module.ts

@Module({
  imports: [
    UsersModule,
    PassportModule,
    JwtModule.register({
      secret: process.env.JWT_SECRET_KEY,
      signOptions: { expiresIn: '4h' },
    }),
  ],
  providers: [AuthService, UsersService, LocalStrategy, JwtStrategy],
  controllers: [AuthController],
})
export class AuthModule {}

auth.controller.ts

@Controller('auth')
export class AuthController {
  constructor(
    private authService: AuthService,
    private usersService: UsersService,
  ) {}

  @UseGuards(LocalAuthGuard)
  @Post()
  async login(@Request() req) {
    return this.authService.login(req.user);
  }
}

auth.service.ts

@Injectable()
export class AuthService {
  constructor(
    private usersService: UsersService,
    private jwtService: JwtService,
  ) {}

  async login(user: any) {
    const payload = { username: user.username, sub: user.id };
    console.log(process.env.JWT_SECRET_KEY);
    return {
      access_token: this.jwtService.sign(payload),
    };
  }
}

console error

// console.log(process.env.JWT_SECRET_KEY)
fb8C47vylwS
[Nest] 50225  - 01/07/2022, 17:46:37   ERROR [ExceptionsHandler] secretOrPrivateKey must have a value
Error: secretOrPrivateKey must have a value
    at Object.module.exports [as sign] (/Users/user/dev/backend/pol-api/node_modules/jsonwebtoken/sign.js:107:20)
    at JwtService.sign (/Users/user/dev/backend/pol-api/node_modules/@nestjs/jwt/dist/jwt.service.js:28:20)
    at AuthService.login (/Users/user/dev/backend/pol-api/src/auth/auth.service.ts:26:37)
    at AuthController.login (/Users/user/dev/backend/pol-api/src/auth/auth.controller.ts:29:29)
    at /Users/user/dev/backend/pol-api/node_modules/@nestjs/core/router/router-execution-context.js:38:29
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at /Users/user/dev/backend/pol-api/node_modules/@nestjs/core/router/router-execution-context.js:46:28
    at /Users/user/dev/backend/pol-api/node_modules/@nestjs/core/router/router-proxy.js:9:17

As I said I tried different potential solutions I found in other similar questions, (like this one) but none of the answers worked for me.

Share Improve this question edited Jul 1, 2022 at 18:40 Progman 19.6k7 gold badges54 silver badges80 bronze badges asked Jul 1, 2022 at 15:55 carloberdcarloberd 1312 silver badges12 bronze badges
Add a comment  | 

4 Answers 4

Reset to default 13

I'm late to the party, but I was just banging my head against this problem and just found a solution.

The problem is probably on this row in app.module.ts:

providers: [UsersService, AuthService, PolsService, JwtService],

JwtService should not be added as a provider. If you do, it seems to reset any registered options.

you can change

secret: process.env.JWT_SECRET_KEY

to

secret: `${process.env.JWT_SECRET_KEY}`

You are importing the ConfigModule in the AppModule, but not as a global module so your AuthModule does not know about it. That is why it does not know the secret.

You can either import the ConfigModule in the AuthModule as well or import it as a global module from within the AppModule.

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
    }),
    ...
  ],
  ...
})
export class AppModule {}

Then in the AuthModule register the JwtModule asynchronously using registerAsync. Use a factory in which you inject the ConfigService exported from the ConfigModule.

@Module({
  imports: [
    UsersModule,
    PassportModule,
    JwtModule.registerAsync({
      useFactory: (configService: ConfigService) => {
        return {
          secret: configService.get<string>('JWT_SECRET_KEY'),
          signOptions: { expiresIn: '60s' },
        };
      },
      inject: [ConfigService],
    }),
  ],
  ...
})
export class AuthModule {}

The ConfigModule as imported in the AppModule reads the .env file in an async I/O op. By registering the JwtModule asynchronously and injecting the ConfigService dependency you are making it wait until the ConfigModule has been loaded and the .env file has been read. Just use the ConfigService to read the environment variable and cast it.

More information about using the ConfigService can be found in NestJS's documentation.

https://docs.nestjs.com/techniques/configuration#using-the-configservice

Try removing JwtService and AuthService from the providers in app.module.ts. Also remove AuthController from the controllers in app.module.ts.

This worked for me when I had the same error message. Although I am not entirely sure yet why this works (I am very new to NestJS), here is my reasoning:

You pass the AuthModule (which already contains the AuthController and AuthService) to be imported in the AppModule. By adding AuthController and AuthService again at the root (AppModule) level, I believe you defeat the purpose of having the AuthModule in the first place and do not use the module context. By adding JwtService to the AppModule providers, you override the JwtService registered in the AuthModule context with an empty one.

Again, I am new to NestJS, so corrections are very welcome.

Edit:
I assume you were following the documentation, which unfortunately does not show the AppModule. They do however link to the GitHub repository where only the Module (not the Service) are imported:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AuthModule } from './auth/auth.module';
import { UsersModule } from './users/users.module';

@Module({
  imports: [AuthModule, UsersModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

I hope this helps.

发布评论

评论列表(0)

  1. 暂无评论