token refresh

This commit is contained in:
Julian Krauser 2024-08-23 14:42:47 +02:00
parent bcfba8b448
commit 55caf69bf0
4 changed files with 102 additions and 8 deletions

View file

@ -3,6 +3,6 @@ export interface CreateRefreshCommand {
}
export interface DeleteRefreshCommand {
id: number;
token: string;
userId: number;
}

View file

@ -2,9 +2,10 @@ import { dataSource } from "../data-source";
import { refresh } from "../entity/refresh";
import InternalException from "../exceptions/internalException";
import { JWTHelper } from "../helpers/jwtHelper";
import { StringHelper } from "../helpers/stringHelper";
import UserService from "../service/userService";
import { JWTRefresh } from "../type/jwtTypes";
import { CreateRefreshCommand } from "./refreshCommand";
import { CreateRefreshCommand, DeleteRefreshCommand } from "./refreshCommand";
import ms from "ms";
export default abstract class RefreshCommandHandler {
@ -14,10 +15,11 @@ export default abstract class RefreshCommandHandler {
* @returns {Promise<string>}
*/
static async create(createRefresh: CreateRefreshCommand): Promise<string> {
let createRefreshToken: JWTRefresh = {
userId: createRefresh.userId,
};
const refreshToken = await JWTHelper.create(createRefreshToken);
// let createRefreshToken: JWTRefresh = {
// userId: createRefresh.userId,
// };
// const refreshToken = await JWTHelper.create(createRefreshToken);
const refreshToken = StringHelper.random(32);
return await dataSource
.createQueryBuilder()
@ -26,7 +28,7 @@ export default abstract class RefreshCommandHandler {
.values({
token: refreshToken,
user: await UserService.getById(createRefresh.userId),
expiry: ms(process.env.REFRESH_EXPIRATION),
expiry: new Date(Date.now() + ms(process.env.REFRESH_EXPIRATION)),
})
.execute()
.then((result) => {
@ -36,4 +38,23 @@ export default abstract class RefreshCommandHandler {
throw new InternalException("Failed saving refresh token");
});
}
/**
* @description delete refresh by user and token
* @param DeleteRefreshCommand
* @returns {Promise<refresh>}
*/
static async deleteByToken(deleteRefresh: DeleteRefreshCommand): Promise<any> {
return await dataSource
.createQueryBuilder()
.delete()
.from(refresh)
.where("refresh.token = :token", { token: deleteRefresh.token })
.andWhere("refresh.userId = :userId", { userId: deleteRefresh.userId })
.execute()
.then((res) => {})
.catch((err) => {
throw new InternalException("failed refresh removal");
});
}
}

View file

@ -1,6 +1,6 @@
import { Request, Response } from "express";
import { JWTHelper } from "../helpers/jwtHelper";
import { JWTToken } from "../type/jwtTypes";
import { JWTData, JWTToken } from "../type/jwtTypes";
import InternalException from "../exceptions/internalException";
import RefreshCommandHandler from "../command/refreshCommandHandler";
import { CreateRefreshCommand } from "../command/refreshCommand";
@ -10,6 +10,8 @@ import UnauthorizedRequestException from "../exceptions/unauthorizedRequestExcep
import QRCode from "qrcode";
import { CreateUserCommand } from "../command/userCommand";
import UserCommandHandler from "../command/userCommandHandler";
import RefreshService from "../service/refreshService";
import BadRequestException from "../exceptions/badRequestException";
/**
* @description Check authentication status by token
@ -80,6 +82,51 @@ export async function logout(req: Request, res: Response): Promise<any> {}
export async function refresh(req: Request, res: Response): Promise<any> {
let token = req.body.token;
let refresh = req.body.refresh;
const tokenUser = await JWTHelper.decode(token);
if (typeof tokenUser == "string" || !tokenUser) {
throw new InternalException("process failed");
}
let tokenUserId = (tokenUser as JWTToken).userId;
let { user } = await RefreshService.getByToken(refresh);
if (tokenUserId != user.id) {
throw new UnauthorizedRequestException("user not identified with token and refresh");
}
let { id, username } = await UserService.getById(tokenUserId);
let jwtData: JWTToken = {
userId: id,
username: username,
rights: [],
};
let accessToken: string;
let refreshToken: string;
JWTHelper.create(jwtData)
.then((result) => {
accessToken = result;
})
.catch((err) => {
console.log(err);
throw new InternalException("Failed accessToken creation");
});
let refreshCommand: CreateRefreshCommand = {
userId: id,
};
refreshToken = await RefreshCommandHandler.create(refreshCommand);
await RefreshCommandHandler.deleteByToken(refresh);
res.json({
accessToken,
refreshToken,
});
}
/**

View file

@ -0,0 +1,26 @@
import { dataSource } from "../data-source";
import { refresh } from "../entity/refresh";
import InternalException from "../exceptions/internalException";
export default abstract class RefreshService {
/**
* @description get refresh by token
* @param token string
* @returns {Promise<refresh>}
*/
static async getByToken(token: string): Promise<refresh> {
return await dataSource
.getRepository(refresh)
.createQueryBuilder("refresh")
.leftJoinAndSelect("refresh.user", "user")
.where("refresh.token = :token", { token: token })
.andWhere("refresh.expiry >= :expiry", { expiry: new Date() })
.getOneOrFail()
.then((res) => {
return res;
})
.catch((err) => {
throw new InternalException("refresh not found");
});
}
}