I'm building this API using JWT and NestJS. This is an API for a mobile application so I need the JWT Token to be constantly refreshed. The idea is to check the incoming token request, if the token is expired, JWT will thrown an error message saying token expired. If that's the case the token will be refreshed, if it's another error it will throw an error.
I also have a GetUser decorator that would return the user from the HttpRequest, but now that I'm using a custom AuthGuard I can't get it to work. Any tips?
AuthGuard.ts
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { LoginService } from 'src/users/login.service';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(
private loginService: LoginService,
private jwtService: JwtService
) {}
async canActivate( context: ExecutionContext ) {
const request = context.switchToHttp().getRequest();
const { headers } = request;
const headerString = headers.authorization.split(' ');
const currentToken = await this.loginService.validateToken(headerString[1]);
return currentToken ? true : false;
}
}
LoginService.ts
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { JwtService, JwtSignOptions } from '@nestjs/jwt';
@Injectable()
export class LoginService {
constructor(
private jwtService: JwtService
) { }
async validateToken(token: string): Promise<any> {
try {
const verifiedToken = await this.jwtService.verify(token, { secret: process.env.JWT_SECRET });
return verifiedToken;
} catch (error) {
if (error.message === 'jwt expired' ) {
const newToken = await this.refreshToken(token);
return newToken;
} else {
throw new UnauthorizedException();
}
}
}
async refreshToken(token: string | any ): Promise<any> {
const decodedToken = await this.jwtService.decode(token) as any;
const { email, id } = decodedToken;;
const payload = { email, id };
const options: JwtSignOptions = {
secret: process.env.JWT_SECRET,
expiresIn: '2w'
};
const accessToken = await this.jwtService.sign(payload, options);
return { accessToken };
}
}
userDecorator.ts
import { createParamDecorator, ExecutionContext } from "@nestjs/common";
import { User } from "./user.entity";
export const GetUser = createParamDecorator( (data, ctx: ExecutionContext): User => {
const req = ctx.switchToHttp().getRequest();
return req.user;
});
Any help will be greatly appreciated! Thanks