Home > Mobile >  Nest.js add global jwt service
Nest.js add global jwt service

Time:01-04

I would like to add my jwt service as global service. But its not work in CanActivate(my guard). More precisely, he comes there, but does not have a secret key

This is my code: Register service as global

forwardRef(() => UsersModule),
{
  ...JwtModule.registerAsync({
    useFactory: (configService: ConfigService) => ({
      secret: configService.get<string>('PRIVATE_KEY'),
      signOptions: {
        expiresIn: '24h',
      },
    }),
    inject: [ConfigService],
  }),
  global: true,
},

My Jwt

@Injectable()
export class JwtAuthGuard implements CanActivate {
  constructor(private jwtService: JwtService) {}

  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const req = context.switchToHttp().getRequest();
    try {
      const authHeader = req.headers.authorization;
      const [bearer, token] = authHeader.split(' ');

      if (bearer.toLowerCase() !== 'bearer' || !token)
        throw new UnauthorizedException({
          message: 'Пользователь не авторизован',
        });
      const user = this.jwtService.verify(token);
      req.user = user;
      return true;
    } catch (e) {
      console.log(e);
      throw new UnauthorizedException({
        message: 'Пользователь не авторизован',
      });
    }
  }
}

My auth module

@Module({
  controllers: [AuthController],
  providers: [JwtService],
  imports: [forwardRef(() => UsersModule)],
  exports: [],
})
export class AuthModule {}

CodePudding user response:

To take @nestjs/jwt's JwtModule and make it global, you need to add it to a global wrapper module and export the JwtModule in that wrapper. Something like this:

@Global()
@Module({
  imports: [
    JwtModule.registerAsync({
      useFactory: (configService: ConfigService) => ({
        secret: configService.get<string>('PRIVATE_KEY'),
        signOptions: {
          expiresIn: '24h',
        },
      }),
      inject: [ConfigService],
    }),
  ],
  exports: [JwtModule]
})
export class GlobalJwtModule {}

Now as long as GlobalJwtModule is added to your AppModule the JwtService will be globally injectable

CodePudding user response:

If you haven't provided Strategies to AuthModule it will not trigger CanActive implementation.

@Module({
  imports: [
    forwardRef(() => UsersModule),
    JwtModule.registerAsync({
      imports: [ConfigModule],
      useFactory: async (configService: ConfigService) => ({
        secret: configService.get<string>('PRIVATE_KEY'),
        signOptions: {
          expiresIn: '1d',
        },
      }),
      inject: [ConfigService],
    }),
  ],
  controllers: [AuthController],
  providers: [AuthService, LocalStrategy, JwtStrategy], <=== important here!!
  exports: [AuthService],
})

Moreover, if you want to use the Jwt App Guard as global you might need to provide it to AppModule in app.module.ts like this.

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    UsersModule,
    AuthModule,
  ],
  controllers: [AppController],
  providers: [
    AppService,
    {
      provide: APP_GUARD,
      useClass: JwtAuthGuard,
    },
  ],
})
export class AppModule {}
  • Related