Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialize Guard with value

Is it possible to initialize guard with a specifig value ? For example the current example will not work:

@Module({
  imports: [
    CoreModule,
  ],
  providers: [
    {
      provide: AuthGuard, // while using APP_GUARD works
      useFactory: (configService: ConfigService) => {
        return new AuthGuard(configService.get('some_key'));
      },
      inject: [ConfigService],
    },
  ],
})

While using APP_GUARD for provide will initialise the guard with config value. So it works only for global scope, but not for @UseGuards(AuthGuard)

like image 935
user2623505 Avatar asked Sep 02 '25 11:09

user2623505


2 Answers

This doesn't work because guards are not registered as providers in a module. They get directly instantiated by the framework.

You can either use dependency injection in the guard:

@Injectable()
export class MyAuthGuard {
  constructor(private readonly configService: ConfigService) {
    // use the configService here
  }
}

and

@UseGuards(MyAuthGuard)

or instantiate the guard yourself:

@UseGuards(new AuthGuard(configService.get('some_key')))

In the special case of the AuthGuard, you can set a defaultStrategy in the PassportModule. Then you can just use @UseGuards(AuthGuard())

PassportModule.register({ defaultStrategy: 'jwt'}) 

or async:

PassportModule.registerAsync({
  imports: [ConfigModule],
  useFactory: async (configService: ConfigService) => ({ defaultStrategy: configService.authStrategy}),
  inject: [ConfigService],
}) 
like image 144
Kim Kern Avatar answered Sep 03 '25 23:09

Kim Kern


Let's say you want your specific guard instance to perform differently depending on some input, basically be able to configure it. There is no option to consume this config from constructor(). Factory way might look like a bit bulky solution. But you're still able to utilise static methods to achieve wanted behaviour.

Example:

@Injectable()
class SomeController {
  @Get()
  @UseGuard(AuthGuard) // but how to pass smth inside AuthGuard?
  public async doSomething() {}
}

Solution:

// [auth.guard.ts] file
import { UnauthorizedException, Injectable } from '@nestjs/common';
import type { CanActivate, ExecutionContext } from '@nestjs/common';
import type { GuardOptions, PatchedRequest } from './auth.types';


export interface GuardOptions {
  allowAnonymous?: boolean,
  allowExpired?: boolean,
}

@Injectable()
export class AuthGuard
implements CanActivate {
  public options: GuardOptions = {};
  public canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> {
    // Guard logic 
    return true;
  }

  static configure(options: GuardOptions) {
    const instance = new AuthGuard;
    instance.options = options;
    return instance;
  }
}


// [someEntity.controller.ts] file
// imports...

@Injectable()
class SomeController {
  @Get()
  @UseGuard(AuthGuard.configure({ allowExpired: true })) // voila
  public async doSomething() {}
}

Enjoy! Glory to Ukraine!

like image 39
Paul Lucius Valor Avatar answered Sep 04 '25 00:09

Paul Lucius Valor