Estos son los fragmentos de código parciales de NestJS que tengo. Estoy tratando de implementar la estrategia local de pasaporte para obtener el nombre de usuario y la contraseña. Recibo -Error: estrategia de autenticación desconocida "local", en el archivo del controlador cuando uso la protección de autenticación.
AuthModule.ts
import { Module } from '@nestjs/common'; import { JwtModule } from '@nestjs/jwt'; import { PassportModule } from '@nestjs/passport'; import { UserModule } from 'src/user/user.module'; import { JwtAuthController } from './jwt-auth.controller'; import { JwtAuthService } from './jwt-auth.service'; import { JwtStrategy } from './jwt.strategy'; import { LocalStrategy } from './local.strategy'; @Module({ imports: [ UserModule, PassportModule, JwtModule.register({ secret: process.env.SECRETKEY, signOptions: { expiresIn: '3600s' } }) ], controllers: [JwtAuthController], providers: [JwtAuthService, LocalStrategy, JwtStrategy], exports: [JwtAuthService], }) export class JwtAuthModule {}estrategia.local.ts
import { Strategy } from 'passport-local'; import { PassportStrategy } from '@nestjs/passport'; import { Injectable, UnauthorizedException } from '@nestjs/common'; import { JwtAuthService } from './jwt-auth.service'; @Injectable() export class LocalStrategy extends PassportStrategy(Strategy, 'local') { constructor(private authService: JwtAuthService) { super(); } async validate(username: string, password: string): Promise<any> { const user = await this.authService.validateUser({username, password}); if (!user) { throw new UnauthorizedException(); } return user; } }aplicación.controlador.ts
import { Body, Controller, Get, Post, Req, UnauthorizedException, UseGuards } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; import { JwtAuthService } from './jwt-auth/jwt-auth.service'; @Controller() export class AppController { constructor(private readonly authService: JwtAuthService) {} @UseGuards(AuthGuard('local')) @Post('/auth/login') async login(@Req() req) { return this.authService.login(req.user) } }Recibo el siguiente error al llamar a la API /auth/login
[Nest] 26753 - 10/31/2021, 22:08:18 ERROR [ExceptionsHandler] Unknown authentication strategy "local" Error: Unknown authentication strategy "local"¿Me estoy perdiendo algo? Gracias por adelantado.
Corregir error https://github.com/nestjs/nest/issues/4646
Archivo AUTH.ts
enter code here import { Module } from '@nestjs/common'; import { JwtModule } from '@nestjs/jwt'; import { PassportModule } from '@nestjs/passport'; import { UserModule } from 'src/user/user.module'; import { JwtAuthController } from './jwt-auth.controller'; import { JwtAuthService } from './jwt-auth.service'; import { JwtStrategy } from './jwt.strategy'; import { LocalStrategy } from './local.strategy'; @Module({ imports: [ UserModule, PassportModule.register({defaultStrategy:'local'}), JwtModule.register({ secret: process.env.SECRETKEY, signOptions: { expiresIn: '3600s' } }) ], controllers: [JwtAuthController], providers: [JwtAuthService, LocalStrategy, JwtStrategy], exports: [JwtAuthService], }) export class JwtAuthModule {}Una vieja pregunta sin respuestas...
En mi caso, tenía una especie de problema de dependencia cíclica. O al menos era lo que parecía. Las dependencias cíclicas pueden estar en el lado anidado o incluso en el lado requerido de node.js (en el segundo caso, terminamos con importaciones vacías).
Caso 1:
@Injectable() export class MyLocalStrategy extends PassportStrategy(PassportLocalStrategy) { hello = 'hello' constructor(private authService: AuthService) { console.log('load local strategy') } } @Module({ imports: [ CommonModule, PassportModule, JwtModule.registerAsync({ async useFactory(config: ConfigService) { const jwtSecret = config.get('APP_KEY') const expiresIn = config.get('AUTH_TOKEN_EXPIRED') return { secret: jwtSecret, signOptions: { expiresIn, }, } }, inject: [ConfigService], }), ], providers: [ RoleService, JwtStrategy, JwtService, AuthService, ], controllers: [AuthController], exports: [AuthService], }) export class AuthModule { constructor(private moduleRef: ModuleRef) {} onModuleInit() { const moduleRef = this.moduleRef console.log('init auth module') const local = moduleRef.get(MyLocalStrategy) const auth = moduleRef.get(AuthService) console.log('my modules', { local, auth }, local?.hello) } }En este caso, la "estrategia local de carga" nunca se registró. Sin embargo, "mis módulos" registraron una instancia de estrategia local vacía, sin mi propiedad "hola". ¡Extraño!
Hackeé una solución moviendo la creación de instancias de clase a un proveedor de fábrica y requiriendo las dependencias con ModuleRef . El siguiente extracto funcionó bien.
@Module({ imports: [ CommonModule, PassportModule, JwtModule.registerAsync({ async useFactory(config: ConfigService) { const jwtSecret = config.get('APP_KEY') const expiresIn = config.get('AUTH_TOKEN_EXPIRED') return { secret: jwtSecret, signOptions: { expiresIn, }, } }, inject: [ConfigService], }), ], providers: [ RoleService, JwtStrategy, JwtService, AuthService, { provide: MyLocalStrategy, useFactory: (moduleRef: ModuleRef) => { const auth = moduleRef.get(AuthService) console.log('local strat factory', { auth }) return new MyLocalStrategy(auth) }, inject: [ModuleRef], }, ], controllers: [AuthController], exports: [AuthService], }) export class AuthModule { constructor(private moduleRef: ModuleRef) {} onModuleInit() { const moduleRef = this.moduleRef console.log('init auth module') const local = moduleRef.get(MyLocalStrategy) const auth = moduleRef.get(AuthService) console.log('local', { local, auth }, local?.hello) } } También probé factory + inyectando AuthService directamente (a través de la matriz de proveedores, en lugar de usar ModuleRef ). Obtuve un AuthService nulo.
Probablemente algún ciclo de dependencia en las importaciones del módulo node.js, aunque ni eslint ni nest no dirían nada.