Trouble with module import [ NEST JS ]

Viewed 26

I'm trying to use a jwt.strategy.ts to protect my endpoints with jwt verification. Everything was going ok until I decided to import a custom JWTService inside this jwt.strategy which contains its own JWTModule but Nest doesn't seems to recognize it. I can use the JWTService in other services but it doesn't work inside the strategy. What should I do ? What am I doing wrong ?

The NEST Message:

[Nest] 53  - 09/22/2022, 6:32:25 PM   ERROR [ExceptionHandler] Nest can't resolve dependencies of the JwtStrategy (ConfigService, ?). Please make sure that the argument Object at index [1] is available in the AuthModule context.

Potential solutions:
- If Object is a provider, is it part of the current AuthModule?
- If Object is exported from a separate @Module, is that module imported within AuthModule?
  @Module({
    imports: [ /* the Module containing Object */ ]
  })

Error: Nest can't resolve dependencies of the JwtStrategy (ConfigService, ?). Please make sure that the argument Object at index [1] is available in the AuthModule context.

Potential solutions:
- If Object is a provider, is it part of the current AuthModule?
- If Object is exported from a separate @Module, is that module imported within AuthModule?
  @Module({
    imports: [ /* the Module containing Object */ ]
  })

The JWTModule:

import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';

import { jwtOptions } from './jwt.config';
import { JWTService } from './jwt.service';

@Module({
  imports: [JwtModule.registerAsync(jwtOptions)],
  providers: [JWTService],
  exports: [JWTService],
})
export class JWTModule {}

The JWTService:

import { Request } from 'express';
import { DecodeOptions } from 'jsonwebtoken';

import { Injectable, UnprocessableEntityException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { JwtService, JwtSignOptions, JwtVerifyOptions } from '@nestjs/jwt';
import { CookieHttpConfig } from '../auth';

@Injectable()
export class JWTService {
  constructor(
    private readonly jwtService: JwtService,
    private readonly configService: ConfigService,
  ) {}

  sign(payload: string | object | Buffer, options?: JwtSignOptions) {
    return this.jwtService.sign(payload, options);
  }

  async signAsync(payload: string | object | Buffer, options?: JwtSignOptions) {
    return this.jwtService.signAsync(payload, options);
  }

  verify(token: string, options?: JwtVerifyOptions) {
    return this.jwtService.verify(token, options);
  }

  async verifyAsync(token: string, options?: JwtVerifyOptions) {
    return this.jwtService.verifyAsync(token, options);
  }

  decode(token: string, options?: DecodeOptions) {
    return this.jwtService.decode(token, options);
  }

  async getToken(tokenPayload: any): Promise<string> {
    try {
      const token: string = await this.jwtService.signAsync(tokenPayload);

      return `Bearer ${token}`;
    } catch (error) {
      throw new UnprocessableEntityException(error.message);
    }
  }

  async refreshToken(
    cookieName: string,
    request: Request,
    payload: any,
  ): Promise<void> {
    const token: string = await this.getToken(payload);

    request.res.cookie(cookieName, token, CookieHttpConfig.Options());
  }
}

jwt.strategy:

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

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    private readonly configService: ConfigService,
    private readonly jwtService: JWTService,
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromExtractors([
        (request: Request) => {
          try {
            const token = request.signedCookies['Authorization'].split(' ')[1];

            return token;
          } catch (error) {
            return null;
          }
        },
      ]),
      ignoreExpiration: false,
      secretOrKey: configService.get('AUTH_JWT_SECRET'),
    });
  }

  async validate(request: Request, payload: any): Promise<any> {
    const tokenPayload = {
      email: payload.email,
      id: payload.id,
    };

    await this.jwtService.refreshToken('Authorization', request, tokenPayload);

    return tokenPayload;
  }
}

Extra information about my project: I divided the project into a monorepo, so I imported the JWTModule inside the AuthModule but it still doesn't work. The jwt.strategy.ts and the JWTModule is inside a shared lib created at the same level as the apps folders containing the microservices.

The AuthModule:

import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { UsersModule } from '../users/users.module';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import {
  AuthLibModule,
  JWTModule,
  JwtStrategy,
  LocalStrategy,
} from '@app/common';
import { Web3Module } from '../web3/web3.module';
import { VonageModule } from '@app/common';

@Module({
  imports: [
    UsersModule,
    PassportModule,
    JWTModule,
    Web3Module,
    VonageModule,
    AuthLibModule,
  ],
  controllers: [AuthController],
  providers: [AuthService, LocalStrategy, JwtStrategy],
})
export class AuthModule {}
0 Answers
Related