#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],
};
}
}