pirmax
pirmax

Reputation: 2153

Nest can't resolve dependencies of the AuthGuard (Guard decorator)

I've a AuthGuard who check the JWT token in controllers. I want use this Guard in controllers to check authentication. I've this error:

Nest can't resolve dependencies of the AuthGuard (?, +). Please make sure that the argument at index [0] is available in the current context.

TestController.ts

import {
  Controller,
  Post,
  Body,
  HttpCode,
  HttpStatus,
  UseInterceptors,
  UseGuards,
} from "@nestjs/common";
import { TestService } from "Services/TestService";
import { CreateTestDto } from "Dtos/CreateTestDto";
import { ApiConsumes, ApiProduces } from "@nestjs/swagger";
import { AuthGuard } from "Guards/AuthGuard";

@Controller("/tests")
@UseGuards(AuthGuard)
export class TestController {
  constructor(
    private readonly testService: TestService,
  ) {}

  @Post("/create")
  @HttpCode(HttpStatus.OK)
  @ApiConsumes("application/json")
  @ApiProduces("application/json")
  async create(@Body() createTestDto: CreateTestDto): Promise<void> {
    // this.testService.blabla();
  }
}

AuthGuard.ts

import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common";
import { AuthService } from "Services/AuthService";
import { UserService } from "Services/UserService";

@Injectable()
export class AuthGuard implements CanActivate {
    constructor(
        private readonly authService: AuthService,
        private readonly userService: UserService,
    ) {}

    async canActivate(dataOrRequest, context: ExecutionContext): Promise<boolean> {
        try {
            // code is here
            return true;
        } catch (e) {
            return false;
        }
    }
}

Upvotes: 4

Views: 14359

Answers (1)

VinceOPS
VinceOPS

Reputation: 2720

AuthService (the dependency that could not be resolved) must be available in the scope containing the controller which uses the guard.

What does it mean?

Include AuthService in the providers of the module loading your controller.

e.g.

@Module({
  controllers: [TestController],
  providers: [AuthService, TestService, UserService],
})
export class YourModule {}

EDIT - Forgot to mention that an other clean way (maybe cleaner, depending on the context) consists in importing the module that offers (exports) the service.

e.g.

@Module({
  providers: [AuthService],
  exports: [AuthService],
})
export class AuthModule {}

@Module({
  imports: [AuthModule],
  controllers: [TestController],
  providers: [TestService, UserService],
})
export class YourModule {}

Upvotes: 16

Related Questions