Skip to content

Custom AuthChecker not running upon request in TypeGraphQL with NestJS #53

@gabrielbryk

Description

@gabrielbryk

Describe the Bug

The AuthChecker function is not being called when a request is made to a GraphQL endpoint that has @Authorized decorators applied to its resolvers or fields. Despite properly configuring the authChecker option in the TypeGraphQLModule and providing a custom AuthChecker implementation, the authentication logic is not triggered.

To Reproduce

Here's a minimal reproducible example:

// app.module.ts
import { Module } from '@nestjs/common';
import { TypeGraphQLModule } from 'typegraphql-nestjs';
import { CustomAuthChecker } from './authorization/authChecker';
import { AuthorizationGuard } from './authorization/authorization.guard';
import { ConfigModule } from '@nestjs/config';

export interface GraphQLContext {
  req: any;
  res: any;
}

@Module({
  imports: [
    TypeGraphQLModule.forRoot({
      authChecker: CustomAuthChecker,
      authMode: 'error',
      context: ({ req, res }): GraphQLContext => ({
        req,
        res,
      }),
    }),
    ConfigModule.forRoot({
      isGlobal: true,
    }),
  ],
  providers: [AuthorizationGuard],
})
export class AppModule {}

// authorization.guard.ts
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { expressjwt as jwt } from 'express-jwt';
import { promisify } from 'util';
import { expressJwtSecret, GetVerificationKey } from 'jwks-rsa';
import { ConfigService } from '@nestjs/config';

@Injectable()
export class AuthorizationGuard {
  private AUTH0_DOMAIN;
  private AUTH0_AUDIENCE;

  constructor(private configService: ConfigService) {
    this.AUTH0_DOMAIN = this.configService.get('AUTH0_DOMAIN');
    this.AUTH0_AUDIENCE = this.configService.get('AUTH0_AUDIENCE');
  }

  async checkAuth(req: any, res: any): Promise<boolean> {
    try {
      await this.checkJwt(req, res);
      return true;
    } catch (e) {
      return false;
    }
  }

  private async checkJwt(req: any, res: any): Promise<void> {
    const checkJwt = promisify(
      jwt({
        secret: expressJwtSecret({
          cache: true,
          rateLimit: true,
          jwksRequestsPerMinute: 5,
          jwksUri: `https://${this.AUTH0_DOMAIN}/.well-known/jwks.json`,
        }) as GetVerificationKey,
        audience: this.AUTH0_AUDIENCE,
        issuer: this.AUTH0_DOMAIN,
        algorithms: ['RS256'],
      }),
    );

    await checkJwt(req, res);
  }
}

// authChecker.ts
import { AuthCheckerInterface, ResolverData } from 'type-graphql';
import { AuthorizationGuard } from './authorization.guard';
import { Logger } from '@nestjs/common';
import { GraphQLContext } from '../app.module';

export class CustomAuthChecker implements AuthCheckerInterface<GraphQLContext> {
  constructor(private readonly authorizationGuard: AuthorizationGuard) {}

  async check(
    resolverData: ResolverData<GraphQLContext>,
    roles: string[],
  ): Promise<boolean> {
    Logger.debug('Checking auth', 'CustomAuthChecker');
    const { req, res } = resolverData.context;
    try {
      await this.authorizationGuard.checkAuth(req, res);
      return true;
    } catch (error) {
      return false;
    }
  }
}

The CustomAuthChecker is provided to the TypeGraphQLModule via the authChecker option, but when making a request to a GraphQL endpoint decorated with @Authorized, the check method of CustomAuthChecker is not invoked, and consequently, the AuthorizationGuard.checkAuth method is not called.

Expected Behavior

When a request is made to a GraphQL endpoint decorated with @Authorized, the check method of the CustomAuthChecker should be invoked, and the AuthorizationGuard.checkAuth method should be called to perform the authentication logic. If the authentication succeeds, the request should proceed; otherwise, it should be rejected with an unauthorized error.

Logs

The Logger.debug('Checking auth', 'CustomAuthChecker'); statement inside the CustomAuthChecker.check method is not being logged, indicating that the check method is not being invoked.

Environment:

  • OS: Mac
  • Node: v20.10.0
  • Package version: typegraphql-nestjs@0.7.0
  • TypeScript version: 5.3.3

Additional Context

I have followed the documentation and examples provided in the TypeGraphQL and typegraphql-nestjs repositories, but the AuthChecker is still not being triggered. I have also ensured that the @Authorized decorators are properly applied to the resolvers or fields in my GraphQL schema.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions