简体   繁体   中英

NestJS can't resolve dependencies of the JWT_MODULE_OPTIONS

I'm failed to compile with this error:

Nest can't resolve dependencies of the JWT_MODULE_OPTIONS (?). Please make sure that the argument at index [0] is available in the JwtModule context. +52ms

I saw similar dependencies problems with modules & services, but they didn't work for me. Using JwtModule in my auth.module.ts :

import { JwtModule } from '@nestjs/jwt';
@Module({
    imports: [
        TypeOrmModule.forFeature([User, Role]),
        ConfigModule,
        PassportModule.register({ defaultStrategy: 'jwt' }),
        JwtModule.registerAsync({
            inject: [ConfigService],
            useFactory: async (configService: ConfigService) => ({
                secretOrPrivateKey: config.jwtSecret,
                type: configService.dbType as any,
                host: configService.dbHost,
                port: configService.dbPort,
                username: configService.dbUsername,
                password: configService.dbPassword,
                database: configService.dbName,
                entities: ['./src/data/entities/*.ts'],
                signOptions: {
                    expiresIn: config.expiresIn,
                },
            }),
        }),

    ],
    providers: [AuthService, JwtStrategy],
    controllers: [AuthController],
})
export class AuthModule { }

I have no idea how to fix this bug... Using jwt 6.1.1

Edit: In my previous project use jwt 6.0.0, so I downgrade it, but problem not fix.

First, you are mixing the TypeORMModule configuration with the JWTModule configuration.

According to @nestjs/jwt source code (and docs ), secretOrPrivateKey and signOptions . All the other parameters seem to be part of the TypeORMModule configuration.

Second, the ConfigService (which is dependency [0] of the JWT module) does not seem to exist anywhere in your code. So you are missing an import to a module where the ConfigService exists inside.

This is why the dependency load is failing (and that is what the error is throwing means)

Note that in your code you are missing an import of a module ( ConfigModule in the following sample), which is the module that holds the ConfigService. Otherwise there is no way to inject this ConfigService from nowhere!

JwtModule.registerAsync({
  imports: [ConfigModule], // Missing this
  useFactory: async (configService: ConfigService) => ({
    signOptions: {
       expiresIn: config.expiresIn,
    },
    secretOrPrivateKey: config.jwtSecret,
  }),
  inject: [ConfigService], 
}),

I somehow got it to work by adding

JwtModule.registerAsync({
  imports: [ConfigModule], // Missing this
  useFactory: async (configService: ConfigService) => ({
    signOptions: {
       expiresIn: config.expiresIn,
    },
    secretOrPrivateKey: config.jwtSecret,
  }),
  inject: [ConfigService], 
}),

in the app.module.ts and auth.module.ts

You can make a separate module for it (SharedModule)

make sure you have the following packages installed

npm i --save @nestjs/jwt
npm i --save @nestjs/passport

(optional, if you go with MongoDB/Mongoose)

  npm i --save @nestjs/mongoose 

shared.module.ts

@NgModule({
   imports: [
      PassportModule.register({
          defaultStrategy: 'jwt',
        }),
        JwtModule.register({
          secret: process.env.JWT_SECRET_KEY,
          signOptions: {
            expiresIn: '2 days',
          },
        }),
    
   ],
   providers: [JwtStrategy],
   exports: [JwtStrategy, PassportModule]
})

jwt.strategy.ts

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(@InjectModel('User') private collection: Model<User>) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: process.env.JWT_SECRET_KEY,
    });
  }

  async validate(payload: JwtPayload): Promise<User> {
    const { username } = payload;
    const user = await this.collection.findOne({ username });

    if (!user) {
      throw new UnauthorizedException('JwtStrategy unauthorized');
    }

    return user;
  }
}

Now where you want to use it, just import in your module SharedModule. In your controllers use the following decorator

@UseGuards(AuthGuard())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM