These are the partial NestJS code snippets I have. I am trying to implement the passport local strategy for getting the username and password. I am getting -Error: Unknown authentication strategy "local", in the controller file when using the auth guard.
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 {}
local.strategy.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;
}
}
app.controller.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)
}
}
I am getting the following error on calling /auth/login API
[Nest] 26753 - 10/31/2021, 22:08:18 ERROR [ExceptionsHandler] Unknown authentication strategy "local"
Error: Unknown authentication strategy "local"
Am I missing anything? Thanks in advance.
Such an old question with no answers...
In my case I was having sort of an cyclic dependency issue. Or at least it was what it looked like. Cyclic deps can be either on nest side or even on node.js require side (on the second case we end up with empty imports).
Case 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)
}
}
In this case the "load local strategy" never got logged. Yet "my modules" logged an empty localStrategy instance, without my "hello" property. Weird!
I hacked a fix by moving the class instantiation to a factory provider, and by requiring the dependencies with ModuleRef. The following excerpt worked fine.
@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)
}
}
I also tried factory + injecting AuthService directly (through providers array, instead of using ModuleRef). I got a null AuthService.
Probably some dependency cycle on the node.js module imports, tough neither eslint or nest wouldn't say anything.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With