Yancey Leo
Yancey Leo

Reputation: 23

nestjs: How to throw an AuthenticationError when I use GraphQL

I write the GqlAuthGuard module, but it always throw an UnauthorizedException when JWT expired or illegal. It will lead to an error in stacktrace.

I want to throw AuthenticationError(from apollo-server-express).

How can I do it?

import { Injectable, ExecutionContext } from '@nestjs/common'
import { AuthGuard } from '@nestjs/passport'
import { GqlExecutionContext } from '@nestjs/graphql'

@Injectable()
export class GqlAuthGuard extends AuthGuard('jwt') {
  public getRequest(context: ExecutionContext) {
    const ctx = GqlExecutionContext.create(context)
    return ctx.getContext().req
  }
}

GraphQL Authorization Error

Upvotes: 2

Views: 2644

Answers (2)

Almaju
Almaju

Reputation: 1383

I had to modify a bit the solution proposed by Jay McDoniel:

import { Injectable, ExecutionContext } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { GqlExecutionContext } from '@nestjs/graphql';
import { AuthenticationError } from 'apollo-server-express';

@Injectable()
export class GqlAuthGuard extends AuthGuard('jwt') {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    try {
      return (await super.canActivate(context)) as boolean;
    } catch (e) {
      throw new AuthenticationError('You are not logged-in.');
    }
  }

  getRequest(context: ExecutionContext) {
    const ctx = GqlExecutionContext.create(context);
    return ctx.getContext().req;
  }
}


Upvotes: 4

Jay McDoniel
Jay McDoniel

Reputation: 70131

You can override the canActivate method from the super class (AuthGuard('jwt')), and from there you can find if the super.canActivate(req) returns a true or false by saving the result to a variable. If false, you can throw your own error there instead of the UnauthorizedException that Nest throws.

import { Injectable, ExecutionContext } from '@nestjs/common'
import { AuthGuard } from '@nestjs/passport'
import { GqlExecutionContext } from '@nestjs/graphql'

@Injectable()
export class GqlAuthGuard extends AuthGuard('jwt') {

  public async canActivate(context: ExecutionContext): Promise<boolean> {
    const result = (await super.canActivate(context)) as boolean;
    if (!result) {
      throw new AuthenticationError('Your Message Here');
    }
    return result;
  }

  public getRequest(context: ExecutionContext) {
    const ctx = GqlExecutionContext.create(context)
    return ctx.getContext().req
  }
}

Upvotes: 2

Related Questions