Code Monkey home page Code Monkey logo

Comments (10)

dzcpy avatar dzcpy commented on May 6, 2024 34

Just for someone who might also want to solve a similar problem. I found this also work well, so you can just import JWT module globally while sparing others:

@Module({
  imports: [
    {
      ...JwtModule.register({
        secret: process.env.SECRET
      }),
      global: true
    }
  ],
  exports: [JwtModule]
})
export class CoreModule {}

from jwt.

kamilmysliwiec avatar kamilmysliwiec commented on May 6, 2024 17

@dzcpy

@Global()
@Module({
  imports: [
    JwtModule.register({
      secret: process.env.SECRET
    })
  ],
  exports: [JwtModule]
})
export class CoreModule {}

then import CoreModule once, in your AppModule.

from jwt.

micalevisk avatar micalevisk commented on May 6, 2024 2

@rostamiani you can open a PR to improve it https://github.com/nestjs/nest/blob/6ffdef14bc9e4a77d8b4b20a302fd864f31c9124/packages/common/interfaces/modules/module-metadata.interface.ts#L32-L36

This is documented here: https://docs.nestjs.com/modules#module-re-exporting

from jwt.

kamilmysliwiec avatar kamilmysliwiec commented on May 6, 2024

Read this chapter https://docs.nestjs.com/modules

Mainly these two:

from jwt.

dzcpy avatar dzcpy commented on May 6, 2024

@wxs77577 Have you found a way to import it globally? After reading the two links above I still found it's a bit difficult to do it

from jwt.

dzcpy avatar dzcpy commented on May 6, 2024

@kamilmysliwiec Thanks very much!

from jwt.

spiotr12 avatar spiotr12 commented on May 6, 2024

Could you just add property to the register method? or something else to match the consistency with other @nestjs packages. Thanks!

from jwt.

rostamiani avatar rostamiani commented on May 6, 2024

The current ts-doc for Module decorator is not good. It just mentions providers not modules:

Optional list of the subset of providers that are provided by this module and should be available in other modules which import this module.

from jwt.

kn327 avatar kn327 commented on May 6, 2024

So, unfortunately it looks like the built in JwtModule does not export very well or very easily unless you're doing it from the core project.

I tried overloading the implementation to try and force the module to be global, but sadly, if it's nested within a second layer module, NestJs does not properly respect the global flag (and I also tried exporting the same module and some variants)

{
   ...
   imports: [
      {
           ...JwtModule.register(options),
           global: true
      }
   ]
   ...
}

What I ended up doing was actually creating a custom JwtService / JwtModule that extended the original capability to make it work.

The only downside is that I cannot import the nestjs JwtService but instead just import the custom JwtDomainService everywhere - but since my service just extends the JwtService it should be a 1:1 change

From the module down:

./jwt-domain.module.ts

import { DynamicModule, Global, Module } from "@nestjs/common";
import {
  JwtModuleAsyncOptions,
  JwtModuleOptions,
} from "@nestjs/jwt";
import { PassportModule } from "@nestjs/passport";
import { JWT_OPTIONS } from "./config";
import { JwtDomainService } from "./services/jwt-domain.service";
import { JwtStrategy } from "./strategies";

@Global()
@Module({})
export class JwtDomainModule {
  static forRoot(options: JwtModuleOptions): DynamicModule {
    const module: DynamicModule = {
      global: true,
      module: JwtDomainModule,
      imports: [PassportModule],
      providers: [
        JwtStrategy,
        JwtDomainService,
        {
          provide: JWT_OPTIONS,
          useValue: options,
        },
      ],
      exports: [JwtDomainService],
    };

    return module;
  }

  static forRootAsync(options: JwtModuleAsyncOptions): DynamicModule {
    const module: DynamicModule = {
      global: true,
      module: JwtDomainModule,
      imports: [...(options.imports || []), PassportModule],
      providers: [
        JwtStrategy,
        JwtDomainService,
        {
          provide: JWT_OPTIONS,
          useFactory: async (...args) => {
            let config = options.useFactory(...args);

            if (config instanceof Promise) config = await config;

            return config;
          },
          inject: options.inject || [],
        },
      ],
      exports: [JwtDomainService],
    };

    return module;
  }
}

./config

export const JWT_OPTIONS = "JWT_OPTIONS";

./services

import { Inject, Injectable } from "@nestjs/common";
import { JwtModuleOptions, JwtService } from "@nestjs/jwt";
import { JWT_OPTIONS } from "../config";

@Injectable()
export class JwtDomainService extends JwtService {
  constructor(@Inject(JWT_OPTIONS) options: JwtModuleOptions) {
    super(options);
  }
}

./strategies

import { Inject, Injectable } from "@nestjs/common";
import { PassportStrategy } from "@nestjs/passport";
import { ExtractJwt, Strategy } from "passport-jwt";

import { JwtTokenPayload } from "../interfaces";
import { JWT_OPTIONS } from "../config";
import { JwtModuleOptions } from "@nestjs/jwt";

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(@Inject(JWT_OPTIONS) options: JwtModuleOptions) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: options.secret,
      jsonWebTokenOptions: { ignoreExpiration: false },
    });
  }

/// JwtTokenPayload is my custom interface that extends the JwtToken to include private claims
  validate(payload: JwtTokenPayload): JwtTokenPayload {
    return payload;
  }
}

from jwt.

mikechabot avatar mikechabot commented on May 6, 2024

Some of the examples here seem a bit too complicated or hacky. Instead of register use registerAsync, and inject the ConfigService.

@Module({
  imports: [
    JwtModule.registerAsync({
      inject: [ConfigService],
      useFactory: async (configService: ConfigService) => {
        return {
          secret: configService.get<string>('JWT_SECRET'),
          signOptions: { expiresIn: '7d' },
        };
      },
    }),
  ],
})

Note, I've configured the ConfigModule as isGlobal. If you haven't done this, you'll need to import the module inside of registerAsync:

JwtModule.registerAsync({
  imports: [ConfigModule],
  inject: [ConfigService],
  ...
}),

from jwt.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.