15

Let's say I have my module defined as below:

@Module({
  imports: [
    PassportModule.register({ defaultStrategy: 'jwt' }),
    JwtModule.register({
      // Use ConfigService here
      secretOrPrivateKey: 'secretKey',
      signOptions: {
        expiresIn: 3600,
      },
    }),
    PrismaModule,
  ],
  providers: [AuthResolver, AuthService, JwtStrategy],
})
export class AuthModule {}

Now how can I get the secretKey from the ConfigService in here?

Kim Kern
  • 43,715
  • 16
  • 163
  • 170
THpubs
  • 7,154
  • 13
  • 60
  • 133

2 Answers2

33

You have to use registerAsync, so you can inject your ConfigService. With it, you can import modules, inject providers and then use those providers in a factory function that returns the configuration object:

JwtModule.registerAsync({
  imports: [ConfigModule],
  useFactory: async (configService: ConfigService) => ({
    secretOrPrivateKey: configService.getString('SECRET_KEY'),
    signOptions: {
        expiresIn: 3600,
    },
  }),
  inject: [ConfigService],
}),

For more information, see the async options docs.

Kim Kern
  • 43,715
  • 16
  • 163
  • 170
  • 2
    Also, you don't need to import ConfigModule if you have already imported it globally in your app module .i.e ConfigModule.forRoot({ isGlobal: true, expandVariables: true, }), – Segun Kess Apr 20 '20 at 04:18
  • @SegunKess that's a pretty nice hint! – Remi Guan Jul 13 '21 at 08:55
-2

Or there is another solution, create an JwtStrategy class, something like this:

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
    constructor(private readonly authService: AuthService) {
        super({
            jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
            secretOrKey: config.session.secret,
            issuer: config.uuid,
            audience: config.session.domain
        });
    }

    async validate(payload: JwtPayload) {
        const user = await this.authService.validateUser(payload);
        if (!user) {
            throw new UnauthorizedException();
        }
        return user;
    }
}

There you are able to pass ConfigService as a parameter to the constructor, but I'm using config just from plain file.

Then, don't forget to place it in array of providers in module.

Regards.

cojack
  • 2,147
  • 14
  • 16
  • you can't pass the `ConfigService` here, because the use of `this` is not allowed in `super()` – Theo Sep 29 '20 at 13:47
  • que? [10 more to go] – cojack Sep 30 '20 at 09:52
  • if you pass the `ConfigService` in the constructor, you can't access it in the `super()` function. https://stackoverflow.com/questions/51896505/this-is-not-allowed-before-superclass-constructor-invocation – Theo Sep 30 '20 at 10:05
  • and why would you need to access it by this there? – cojack Sep 30 '20 at 12:36
  • i was just replying to what you said... You're using a static config file. I'm just telling it won't work with the ConfigService, that's all – Theo Sep 30 '20 at 15:11
  • But even if you pass the ConfigService here you are able to use it without this, just by name of the argument. – cojack Oct 07 '20 at 09:27