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)
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],
})
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With