-
Notifications
You must be signed in to change notification settings - Fork 20
Description
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.