Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NestJS guard crashing server when canActivate is false #1165

Open
SergioArrighi opened this issue Nov 7, 2023 · 3 comments
Open

NestJS guard crashing server when canActivate is false #1165

SergioArrighi opened this issue Nov 7, 2023 · 3 comments

Comments

@SergioArrighi
Copy link

Hello guys,

I am facing an issue while trying to implement a NestJS guard.

Requirement
In the .env file I have a list of usernames to be considered as admin.
Some of the commands can only be used by admins.

Solution
Add a IsAdminGuard checking if the incoming from.username is contained in the admins array.

Error
throw new common_1.ForbiddenException(constants_2.FORBIDDEN_MESSAGE); ^ ForbiddenException: Forbidden resource at canActivateFn (/Users/sergioarrighi/Documents/workspace/nordic-whales-bot/node_modules/@nestjs/core/helpers/external-context-creator.js:157:23) at processTicksAndRejections (node:internal/process/task_queues:96:5) at target (/Users/sergioarrighi/Documents/workspace/nordic-whales-bot/node_modules/@nestjs/core/helpers/external-context-creator.js:73:31)

Expected behaviour
The request gets rejected and server stays operational

To reproduce you can use my guthub repo.
https://github.com/SergioArrighi/nordic-whales-bot

The main service is here.
While the guard is this one..

To reproduce

  • install the app.
  • Create a .env.local file with these properties
    TELEGRAM_BOT_TOKEN=
    ADMINS=[,,...]
  • Run the app with: npm run serve:local
  • Send the command /list with a user not listed as admin

Thanks for the terrific job and best regards

@Mohamadhassan98
Copy link

Any solutions?

@Mohamadhassan98
Copy link

I've fixed this problem this way. May be useful to someone else?

safeguard.interceptor.ts

export abstract class SafeGuardInterceptor
  implements NestInterceptor, CanActivate
{
  abstract canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean>;

  async intercept(context: ExecutionContext, next: CallHandler<any>) {
    let result = false;
    const returnValue = this.canActivate(context);
    if (isObservable(returnValue)) {
      returnValue.subscribe((value) => {
        if (value) {
          return next.handle();
        } else {
          return of(undefined);
        }
      });
      return of(undefined);
    } else {
      result = await returnValue;
      if (result) {
        return next.handle();
      }
      return of(undefined);
    }
  }
}

type Class<I, Args extends any[] = any[]> = new (...args: Args) => I;

export const UseSafeGuards = (...arr: Class<SafeGuardInterceptor>[]) =>
  UseInterceptors(...arr);

admin.guard.ts

@Injectable()
export class AdminGuard extends SafeGuardInterceptor {
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const telegraf = context.getArgByIndex<TelegrafContext>(0);
    // user is a property injected by some middleware, any logic can be used
    return !!telegraf.user?.isAdmin;
  }
}

And used it like other Guards, for updates:

@Update()
@UseSafeGuards(AdminGuard)
export class AdminUpdate {
    // commands or other stuff here
}

@alvinlys
Copy link

based on the sample given, it seems only can use throw new TelegrafException instead of return false

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants