相关文章推荐
冷静的米饭  ·  sprintf以及__int64 ...·  1 年前    · 
紧张的花生  ·  XML 中的 ﹤![CDATA[ ...·  1 年前    · 
孤独的烤地瓜  ·  android - OkHttp ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Does anybody know where I can see the full code of canActivate method in AuthGuard('jwt')? I realized that canActivate method calls JwtStrategy validate method by using console.log() like this:

// jwt.strategy.ts
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    private readonly configService: ConfigService,
    private readonly usersService: UsersService,
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: true,
      secretOrKey: configService.get<string>('JWT_SECRET'),
  async validate(payload: any) {
    try {
      const user = await this.usersService.getUserById(payload.id);
      // console.log is here
      console.log(user);
      return user;
    } catch (e) {
      console.log(e);
      return null;

If I use the original canActivate method, console.log is called. I thought that JwtStrategy is a middleware so the validate method is called whenever there is a request. However, when I try to override canActivate method to add authorization, console.log in JwtStrategy validate method is not called:

// jwt-auth.guard.ts
import { ExecutionContext, Injectable } from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';
import { AuthGuard } from '@nestjs/passport';
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
  getRequest(context: ExecutionContext) {
    const ctx = GqlExecutionContext.create(context);
    return ctx.getContext().req;
  canActivate(context: ExecutionContext): boolean {
    try {
      // Override: handle authorization
      // return true or false
      // Should JwtStrategy.validate(something) be called here?
    } catch (e) {
      console.log(e);
      return false;

Then I tried to find the original code of AuthGuard('jwt') in order to understand its logic, but I was not able to. Any help would be appreciated, thanks!

Okay, so this is gonna be a very fun deep dive into this. Buckle up.

Middleware as express methods do still exist in NestJS; that said, this is not your normal middleware in the sense of Express middleware. As you'v mentioned AuthGuard()#canActivate() ends up calling the appropriate PassportStrategy. These strategies get registered here specifically on lines 40-41 where passport.use() gets called. This registers the passport strategy class's validate method to be used for passport.verify(). Most of the under the hood logic is very abstract and the context while reading it can be lost, so take your time and understand the concepts of classes, mixins (functions that return classes), and inheritance.

Line 51 of AuthGuard is where the passportFn originally gets created, and in this passportFn passport.authenticate gets called (which calls passport.verify under its hood) (reading through Passport's code is even more confusing, so I'll let you run that when you want).

If you want to add some extra logic to your canActivate() method you can end up calling super.canActivate(context) to call the original canActivate() method that ends up calling passport.authenticate() and thus <Strategy>#validate. That could look something like

@Injectable()
export class CustomAuthGuard extends AuthGuard('jwt') {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    // custom logic can go here
    const parentCanActivate = (await super.canActivate(context)) as boolean; // this is necessary due to possibly returning `boolean | Promise<boolean> | Observable<boolean>
    // custom logic goes here too
    return parentCanActivate && customCondition;
                Thank you so much! Then, is there any way to get access to the return value of <Strategy>#validate outside of super.canActivate(context)? For example, the Strategy verifies the token and validate returns the valid payload containing userId. I want to find a user with the userId in the database, and handle authorization using the 'role' of the user which is saved in the database. Or, as my custom strategy already returns the full user entity, so I think being able to get the return value of validate would be enough.
– Ryan Ro
                Jan 4, 2021 at 5:10
                Under the hood, passport will take whatever is returned by validate and set req.user to it, so if you Need <Strategy#<validate>'s return value, you can get it from req.user
– Jay McDoniel
                Jan 4, 2021 at 17:09
                Oh, that's great! To sum up, super.canActivate(context) returns a boolean whether the valid token is issued for the valid user, and after calling it req.user is set, so I can work with further logic using req.user. Thanks for your help!
– Ryan Ro
                Jan 5, 2021 at 1:41
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.