In my NestJS Node application, I have set up JWT authentication using Passport (as per https://docs.nestjs.com/techniques/authentication) however I am attempting to keep the JWT Key in environment files which are retrieved using the built-in ConfigService.
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(private readonly configService: ConfigService) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: configService.get<string>('JWT_KEY'),
signOptions: { expiresIn: '60s' }
});
}
The module is registered as follows:
JwtModule.registerAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => {
return {
secret: configService.get<string>('JWT_KEY')
};
},
inject: [ConfigService]
})
I am getting the following error when starting the app:
api: [Nest] 16244 - 03/27/2020, 10:52:00 [ExceptionHandler] JwtStrategy requires a secret or key +1ms
It appears that the JWTStrategy class is instantiating before the ConfigService is ready to provide the JWT Key and is returning undefined within the Strategy when calling configService.get<string>('JWT_KEY')
.
What am I doing wrong here? How can I ensure that the ConfigService is ready prior to attempting to retrieve any environment variables?
UPDATE: Entire AuthModule is below:
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { JwtStrategy } from './strategies/jwt.strategy';
import { LocalStrategy } from './strategies/local.strategy';
import { SharedModule } from '../shared/shared.module';
import { UsersModule } from '../users/users.module';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { JwtModule } from '@nestjs/jwt';
import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
const passportModule = PassportModule.register({ defaultStrategy: 'jwt' });
@Module({
imports: [
UsersModule,
passportModule,
JwtModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => {
return {
secret: configService.get<string>('JWT_KEY')
};
},
inject: [ConfigService]
})
],
providers: [ConfigService, AuthService, LocalStrategy, JwtStrategy],
controllers: [AuthController],
exports: [passportModule]
})
export class AuthModule {}
It is a way to define custom algorithm/logic to authenticate users. Passport has a lot of strategies like JWT, facebook, google and more.. You extend a strategy and add your custom logic like from where to get the user, how to validate the user and options passed to passport.
JWT stands for JSON Web Tokens. Using JWT effectively can make our applications stateless from an authentication point of view. We will be using the NestJS JWT Authentication using Local Strategy as the base for this application.
A Passport strategy for authenticating with a JSON Web Token. This module lets you authenticate endpoints using a JSON web token. It is intended to be used to secure RESTful endpoints without sessions.
NestJS follows mostly the same security rules as the Node. js server and Express. NestJS has an dedicated security section in its documentation that addresses these topics: Authentication.
I'm going to be willing to bet that the issue is that you are not import
ing the ConfigModule
to the AuthModule
and instead you are adding the ConfigService
to the providers
array directly. This would mean that if ConfigModule
does any sort of set up on the ConfigService
, it won't be happening anymore. What you should have instead is something like this:
@Module({
imports: [
PassportModule.register({defaultStrategy: 'jwt' }),
UserModule,
JwtModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => {
return {
secret: configService.get<string>('JWT_KEY')
};
},
inject: [ConfigService]
}),
ConfigModule,
],
providers: [LocalStrategy, JwtStrategy, AuthService],
controllers: [AuthController],
exports: [PassportStrategy],
})
export class AuthModule {}
Now as long a ConfigModule
exports
ConfigService
, the AuthModule
should fire up just fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With