jie
jie

Reputation: 113

Nestjs:validate function not working with jwt

I'm trying to use jwt in nest following document

Everything is ok, but validate function is not working in jwt.strategy.ts

this is my jwt.strategy.ts:

import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { AuthService } from './auth.service';
import { JwtPayload } from './interfaces/jwt-payload.interface';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(private readonly authService: AuthService) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme('JWT'),
      secretOrKey: 'secretKey',
    });
  }

  async validate(payload: JwtPayload) {
    console.log(payload)
    // const user = await this.authService.validateUser(payload);
    // if (!user) {
    //   throw new UnauthorizedException();
    // }
    // return user;
  }
}

auth.module.ts:


import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { AuthService } from './auth.service';
import { JwtStrategy } from './jwt.strategy';

@Module({
  imports: [
    PassportModule.register({ defaultStrategy: 'jwt' }),
    JwtModule.register({
      secretOrPrivateKey: 'secretKey',
      signOptions: {
        expiresIn: 3600,
      },
    }),
  ],
  providers: [AuthService, JwtStrategy],
})
export class AuthModule {}

app.module.ts:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserModule } from './user/user.module';
import { GraphQLModule } from '@nestjs/graphql';
import { AuthModule } from './auth/auth.module';

@Module({
  imports: [
    TypeOrmModule.forRoot(),
    GraphQLModule.forRoot({
      typePaths: ['./**/*.graphql'],
    }),
    AuthModule,
    UserModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

When i request in postman, I don't got any log, It doesn't seem to enter this validate function.:

enter image description here

this is Complete code

sorry, my English is bad, this is my first-time use stackoverflow, thanks for your help

Upvotes: 11

Views: 10210

Answers (2)

Vugar Abdullayev
Vugar Abdullayev

Reputation: 2095

I would also add my scenario.
Case 1: JWT token is malformed
Basically, when your JWT token is malformed (don't confuse with not valid) the validate function would NOT call. In other words, when you debug token via jwt.io and it shows signature is not valid. It appears from my side even if I was login in succesfully on local via @auth0/auth0-angular, I was not providing audience url(available on APIs section in auth0). The getting started docs was not mentioning this, so below is working code

   // Angular side

    AuthModule.forRoot({
      domain: `${auth.domain}`,
      clientId: 'client-id',
      useRefreshTokens: true,
      audience: `https://${auth.audience}/`
    }),

Case 2: JWT token is not valid

In that case, I found out that URLs provided in JwtStrategy in NestJs, the URLs must be an exact match. So if you forget to add / at the end of the URL, it would not pass AuthGuard.

// NestJs side

export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      secretOrKeyProvider: passportJwtSecret({
        cache: true,
        rateLimit: true,
        jwksRequestsPerMinute: 5,
        jwksUri: `https://${auth.domain}/.well-known/jwks.json`,
      }),
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      audience: `https://${auth.audience}/`,
      issuer: `https://${auth.domain}}/`,
      algorithms: ['RS256'],
    });
  }

  public validate(payload: any): unknown {
    return payload;
  }
}

Upvotes: 1

Kim Kern
Kim Kern

Reputation: 60457

The validate method of your JwtStrategy will only be called when the token has been verified in terms of the encryption (corrrect key was used to sign it, in your case secretKey) and it is not expired. Only after those two things have been checked, validate is called with the payload. With it, you can then e.g. check if the user still exists. So the three steps are:

  1. Token was signed with your secret key
  2. Token is not expired
  3. Custom payload validation

You can use the jwt debugger to manually check steps 1 and 2 for your token.

Upvotes: 14

Related Questions