Пользовательская стратегия NestJS PassportStrategy не зарегистрирована при совместном использовании через библиотеку

#typescript #passport.js #nestjs #nestjs-passport

#typescript #passport.js #nestjs #nestjs-passport

Вопрос:

Мне было поручено изолировать наш модуль аутентификации NestJS в отдельную разделяемую библиотеку, чтобы его можно было повторно использовать между несколькими проектами NestJS. Каждый проект находится в каждом собственном репозитории, а общая библиотека импортируется как пакет npm. Я использую модуль passport NestJS для аутентификации (с использованием токенов jwt) и в основном просто следовал официальной документации о том, как ее реализовать.

Я следовал шаблону других пакетов сообщества NestJS, и до сих пор я перенес большую часть кода аутентификации и убедился, что он может компилироваться и запускаться.

Теперь я столкнулся с проблемой. Приложение больше не распознает пользовательскую стратегию jwt passport после того, как я перенес ее в библиотеку, и я понятия не имею, почему. Я просто получаю исключение:

Неизвестная стратегия аутентификации «jwt»

Пример:

Это стратегия пользовательского паспорта и AuthModule (реальная версия более сложная, но это минимально воспроизводимый пример). Код точно такой же как в «родительском» проекте, так и в новом проекте библиотеки.

 import { Injectable, Module } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-custom';

@Injectable()
export class CustomStrategy extends PassportStrategy(Strategy, 'custom') {
  async validate(request: Request): Promise<any> {
    console.log('Custom validation', request);

    return true;
  }
}

@Module({})
export class AuthModule {
  static forRoot() {
    return {
      module: AuthModule,
      providers: [CustomStrategy],
      exports: [CustomStrategy],
    };
  }
}

 

Вот как я регистрирую его в приложении NestJS:

 import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { AuthModule } from '@my-org/common';        // Library version
// import { AuthModule } from './auth/AuthModule';  // Local version

@Module({
  imports: [
    AuthModule.forRoot(),
    PassportModule.register({ defaultStrategy: 'custom' })
  ]
})
export class CommonModule {}

export class CustomAuthGuard extends AuthGuard('custom') {}
 

Когда на AuthModule ссылаются из того же проекта NestJS, все запускается, и я получаю Custom validation сообщение консоли.

Когда AuthModule импортируется из моей библиотеки npm, я получаю Unknown authentication strategy "custom" исключение из passport всякий раз, когда я делаю запрос.

Код с обеих сторон точно такой же. Использование модуля точно такое же, независимо от того, откуда взят модуль. Общая библиотека настраивается с использованием того же шаблона, что и официальные пакеты NestJS, такие как @nestjs / common и @nestjs / cqrs. Любые другие зарегистрированные службы, экспортируемые библиотекой, работают по назначению (я могу включить еще один минимальный пример, чтобы показать это, если потребуется).

Чего мне не хватает? Как я могу поделиться своей пользовательской стратегией NestJS PassportStrategy, используя отдельный пакет npm?

Я потратил половину своего рабочего дня, пытаясь решить эту проблему, и пока я думаю, что это может иметь какое-то отношение к тому, в каком экземпляре паспорта зарегистрирована стратегия, но я не знаю, как это проверить — или, если это вообще так, как ее решить.

Комментарии:

1. Вы должны импортировать свою стратегию в массив «providers» в @Module decorator зарегистрируйте свою стратегию «jwt» с помощью PassportModule.register({defaultStrategy: ‘jwt’ }) в массиве «imports»

Ответ №1:

СТРАТЕГИИ:

 import { Strategy } from 'passport-custom';
import { PassportStrategy } from '@nestjs/passport';
import {Injectable, UnauthorizedException} from '@nestjs/common';

@Injectable()
export class CustomStrategy extends PassportStrategy(Strategy, "custom") {
    static key = "custom"

    async validate(req: Request): Promise<User> {
        const valid = true;
        if(!valid) throw new UnauthorizedException();
        return {id: "123", name: "test"};
    }
}
 

Модуль аутентификации:

 @Module({
  imports: [PassportModule],
  providers: [CustomStrategy]
})
export class AuthModule {}
 

Декоратор контроллера:

 @UseGuards(AuthGuard(CustomStrategy.key))
 

Ответ №2:

Что-то вроде этого работает для меня:

 import { Injectable, Module } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-custom';

@Injectable()
export class CustomStrategy extends PassportStrategy(Strategy, 'custom') {
  async validate(request: Request): Promise<any> {
    console.log('Custom validation', request);

    return true;
  }
}

@Module({})
export class AuthModule {
  static forRoot() {
    return {
      module: AuthModule,
      imports: [
        PassportModule.register({ defaultStrategy: 'custom' }),
      ],
      providers: [CustomStrategy],
      exports: [CustomStrategy, PassportModule],
    };
  }
}