#Is there anyway to set metadata in a Guard?

5 messages · Page 1 of 1 (latest)

agile hatch
#

Like this, but this doesn't seem to work:

import { CanActivate, ExecutionContext, Injectable, SetMetadata } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { IAuthGuard, Type } from '@nestjs/passport';
import { NO_AUTH_KEY } from '../access/access.decorator';
import { JwtAuthGuard } from '../jwt/jwt.guard';
import { SSOGuard } from '../sso/sso.guard';

@Injectable()
export class AnyGuard implements CanActivate {
  private guards: Type<IAuthGuard>[] = [JwtAuthGuard, SSOGuard];

  constructor(private reflector: Reflector) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    console.log(this.reflector?.get(NO_AUTH_KEY, context.getHandler())); // true
    SetMetadata(NO_AUTH_KEY, false);
    console.log(this.reflector?.get(NO_AUTH_KEY, context.getHandler())); // false
    return true;
  }
}
deep hare
#

What's the use case?

agile hatch
#

okay so I hope I can explain it well enough...

I have 2 Auth guards (JWT, SSO) and 1 Access guard, in one of the resolvers I want an endpoint to be accesable by specific users only BUT be authenticated by both JWT and SSO

Resolver:

@Resolver(() => [User, Feature])
@UseGuards(JwtAuthGuard, AccessGuard)
export class UserResolver {
  constructor(private readonly userService: UserService) {}

  @Query(() => [User])
  getUsers(): Promise<User[]> {
    ...
  }

  @NoClassAuth() // <-- bypass Class Auth
  @UseGuards(AnyGuard, AccessGuard)
  @Access(AccessType.Admin)
  @Query(() => [User])
  getAdminUser(@Args('id' id: number): Promise<User[]> {
    ...
  }
}

After using the @NoClassAuth() metadata it will always be true but I want to be able to use AccessGuard after the initial skip

AccessGuard:

@Injectable()
export class AccessGuard implements CanActivate {
  constructor(private reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    const NoClassAuth = this.reflector?.get<boolean>(
      NO_AUTH_KEY,
      context.getHandler()
    );

    if (NoClassAuth) {
      return true;
    }

    // ... access loginc
  }
}
deep hare
#

Okay. So what does access guard actually set up and do here? Is there a reason to have it guard the entire class while still wanting to skip it and then use it? Couldn't you just let it run and then run the sso guard after it, letting the sso fail and blocking the request?

agile hatch
#

i mean