68 lines
2.6 KiB
TypeScript
68 lines
2.6 KiB
TypeScript
import { randomBytes } from "node:crypto";
|
|
|
|
import DayJs from "dayjs";
|
|
import { inject, injectable } from "inversify";
|
|
import jwt, { SignOptions, TokenExpiredError } from "jsonwebtoken";
|
|
|
|
import { TokenRepository } from "./token.repository";
|
|
import { AuthTokenPayload, TokenType } from "../../common/types/jwt.type";
|
|
import { jwtExpiredErr } from "../../core/app/app.errors";
|
|
import { Logger } from "../../core/logging/logger";
|
|
import { IOCTYPES } from "../../IOC/ioc.types";
|
|
|
|
@injectable()
|
|
export class TokenService {
|
|
private logger = new Logger(TokenService.name);
|
|
@inject(IOCTYPES.TokenRepository) private tokenRepository: TokenRepository;
|
|
private jwtSecret: string = process.env.JWT_SECRET;
|
|
private jwt_access_expire: string = process.env.JWT_EXPIRE_ACCESS || "2"; //minutes
|
|
private jwt_refresh_expire: string = process.env.JWT_EXPIRE_REFRESH || "2"; //day
|
|
|
|
public _generateToken(type: TokenType, payload: AuthTokenPayload, option?: SignOptions) {
|
|
if (type == "Access" && option?.expiresIn) return jwt.sign(payload, this.jwtSecret, { ...option });
|
|
const refToken = randomBytes(24).toString("hex");
|
|
return refToken;
|
|
}
|
|
public async generateAuthTokens(payload: AuthTokenPayload) {
|
|
const accessToken = this._generateToken("Access", payload, { expiresIn: `${this.jwt_access_expire}m` });
|
|
const refreshToken = this._generateToken("Refresh", payload);
|
|
const RefreshExpire = DayJs().add(+this.jwt_refresh_expire, "day").toDate();
|
|
|
|
const oldToken = await this.tokenRepository.findByUserId(payload.sub);
|
|
if (oldToken) {
|
|
await this.tokenRepository.delete(oldToken._id.toString());
|
|
}
|
|
await this.tokenRepository.model.create({ refreshToken, userId: payload.sub, refreshTokenExpire: RefreshExpire });
|
|
|
|
const tokens = {
|
|
accessToken: {
|
|
token: accessToken,
|
|
expires: DayJs().add(+this.jwt_access_expire, "m").unix().toString(),
|
|
},
|
|
refreshToken: {
|
|
token: refreshToken,
|
|
expires: DayJs().add(+this.jwt_refresh_expire, "day").unix().toString(),
|
|
},
|
|
};
|
|
return tokens;
|
|
}
|
|
|
|
public async revokeTokens(id: string) {
|
|
// const deletedToken = await this.tokenRepository.delete(id);
|
|
// if (!deletedToken) return false;
|
|
// return true;
|
|
|
|
return !!(await this.tokenRepository.delete(id));
|
|
}
|
|
public verifyToken(token: string): AuthTokenPayload {
|
|
try {
|
|
const decoded = jwt.verify(token, this.jwtSecret);
|
|
return decoded as AuthTokenPayload;
|
|
} catch (error) {
|
|
if (error instanceof TokenExpiredError) throw new jwtExpiredErr();
|
|
this.logger.error("error in jwt verify", error);
|
|
throw error;
|
|
}
|
|
}
|
|
}
|