Consider that I have two routes in NestJS, called "signUp" and "validate-code", both of which are inside the SignupModule.
For the signUp route, I return an accessToken using JWT. Here's the code:
const payload = {
mobileNumber: user.mobileNumber
};
return [
{...userData,accessToken: this.jwtService.sign(payload),}
];
After sending the mobile number as a request using Postman to the server, everything works fine and I get an accessToken.
Now, I want to use this accessToken to authorize the validate-code route and check if the user has already registered and their information exists in the database. I have to send the mobileNumber and code to this route along with the accessToken that I received previously through the signUp route. I set the accessToken in Postman as Bearer, but it gives me the following message:
{
"statusCode": 401,
"message": "Unauthorized"
}
The classes written for JWT are as follows:
import {Injectable} from "@nestjs/common";
import {AuthGuard} from "@nestjs/passport";
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
}
//---------------------------------------------------------------
import {AuthGuard} from '@nestjs/passport';
import {Injectable} from "@nestjs/common";
@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {
}
//---------------------------------------------------------------
import {PassportStrategy} from "@nestjs/passport";
import {ExtractJwt} from "passport-jwt";
import {Strategy} from "passport-local";
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: `${process.env.JWT_SECRET}`,
ignoreExpiration: false,
passReqToCallback: true,
});
}
async validate(payload: any) {
return {
mobileNumber: payload.mobileNumber
};
}
}
//---------------------------------------------------------------
import {Injectable, UnauthroziedException} from "@nestjs/common";
import {PassportStrategy} from "@nestjs/passport";
import {Strategy} from 'passport-local';
import {SignupService} from "./signup.service";
@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
constructor(private readonly signupService: SignupService) {
super();
}
async validate(mobileNumber: string) {
const user = await this.signupService.validateUser(mobileNumber);
if (!user) {
throw new UnauthroziedException();
}
return user;
}
}
The signUp route in the SignupController:
@Post('signup')
async signUp(@Body() dto: SignupDto, @Res() res: Response):Promise<Response<any,Record<string, any>>> {
const result = await this.authService.signUp(dto.mobileNumber);
return res.status(result ? HttpStatus.CREATED : HttpStatus.INTERNAL_SERVER_ERROR).json({'message':result});
}
The validate-code route in the SignupController:
@UseGuards(LocalAuthGuard)
@Post('validate-code')
async validateCode(@Body() dto:VerifyCodeDto,@Res() res:Response):Promise<Response<any,Record<string, any>>>{
const [statusCode,data] = await this.authService.verifyCode(dto);
return res.status(statusCode).json(data);
}
Finally, the SignupModule is implemented to use JWT and Passport:
@Module({
imports: [
JwtModule.register({
secret: `${process.env.JWT_SECRET}`,
signOptions: { expiresIn: '60s' },
}),
ThrottlerModule.forRoot(
{
ttl: 30,
limit: 6
}
),
PrismaModule,
ApiModule
],
controllers: [AuthController],
providers: [
JwtStrategy,
LocalStrategy,
SignupService,
{
provide: APP_GUARD,
useClass: ThrottlerGuard
}
]
})
export class SignupModule {
}
So, I have no problem with the signUp route and getting the accessToken, but I cannot use it for the validate-code route. What could be the problem?


This can happen for two reasons:
validatefunction didn't run at all: this may occur when the token is not valid or already expired, you have to verify thatprocess.env.JWT_SECRETis properly passed tosecretandsecretOrKey. also make sure the token created is encrypted with the same string. if the token is not valid or expired then thevalidatefunction will not run and you getUnauthorizedasmessagevalue in the response.validatefunction is running butthis.signupService.validateUser(mobileNumber)is returning a "falsy" result souseris not defined thereforenew UnauthroziedException()is thrown.Note: I usually work with only one strategy but here you are using two
the first one:
the second one:
then you add
@UseGuards()withLocalAuthGuardto your@Post('validate-code')route but I can't see from the code any indication thatLocalAuthGuardshould useLocalStrategyas strategy, make sure the expectedvalidatefunction is running.from Nestjs docs about named strategies: