token refresh
This commit is contained in:
parent
bcfba8b448
commit
55caf69bf0
4 changed files with 102 additions and 8 deletions
|
@ -3,6 +3,6 @@ export interface CreateRefreshCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DeleteRefreshCommand {
|
export interface DeleteRefreshCommand {
|
||||||
id: number;
|
token: string;
|
||||||
userId: number;
|
userId: number;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,10 @@ import { dataSource } from "../data-source";
|
||||||
import { refresh } from "../entity/refresh";
|
import { refresh } from "../entity/refresh";
|
||||||
import InternalException from "../exceptions/internalException";
|
import InternalException from "../exceptions/internalException";
|
||||||
import { JWTHelper } from "../helpers/jwtHelper";
|
import { JWTHelper } from "../helpers/jwtHelper";
|
||||||
|
import { StringHelper } from "../helpers/stringHelper";
|
||||||
import UserService from "../service/userService";
|
import UserService from "../service/userService";
|
||||||
import { JWTRefresh } from "../type/jwtTypes";
|
import { JWTRefresh } from "../type/jwtTypes";
|
||||||
import { CreateRefreshCommand } from "./refreshCommand";
|
import { CreateRefreshCommand, DeleteRefreshCommand } from "./refreshCommand";
|
||||||
import ms from "ms";
|
import ms from "ms";
|
||||||
|
|
||||||
export default abstract class RefreshCommandHandler {
|
export default abstract class RefreshCommandHandler {
|
||||||
|
@ -14,10 +15,11 @@ export default abstract class RefreshCommandHandler {
|
||||||
* @returns {Promise<string>}
|
* @returns {Promise<string>}
|
||||||
*/
|
*/
|
||||||
static async create(createRefresh: CreateRefreshCommand): Promise<string> {
|
static async create(createRefresh: CreateRefreshCommand): Promise<string> {
|
||||||
let createRefreshToken: JWTRefresh = {
|
// let createRefreshToken: JWTRefresh = {
|
||||||
userId: createRefresh.userId,
|
// userId: createRefresh.userId,
|
||||||
};
|
// };
|
||||||
const refreshToken = await JWTHelper.create(createRefreshToken);
|
// const refreshToken = await JWTHelper.create(createRefreshToken);
|
||||||
|
const refreshToken = StringHelper.random(32);
|
||||||
|
|
||||||
return await dataSource
|
return await dataSource
|
||||||
.createQueryBuilder()
|
.createQueryBuilder()
|
||||||
|
@ -26,7 +28,7 @@ export default abstract class RefreshCommandHandler {
|
||||||
.values({
|
.values({
|
||||||
token: refreshToken,
|
token: refreshToken,
|
||||||
user: await UserService.getById(createRefresh.userId),
|
user: await UserService.getById(createRefresh.userId),
|
||||||
expiry: ms(process.env.REFRESH_EXPIRATION),
|
expiry: new Date(Date.now() + ms(process.env.REFRESH_EXPIRATION)),
|
||||||
})
|
})
|
||||||
.execute()
|
.execute()
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
|
@ -36,4 +38,23 @@ export default abstract class RefreshCommandHandler {
|
||||||
throw new InternalException("Failed saving refresh token");
|
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");
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import { JWTHelper } from "../helpers/jwtHelper";
|
import { JWTHelper } from "../helpers/jwtHelper";
|
||||||
import { JWTToken } from "../type/jwtTypes";
|
import { JWTData, JWTToken } from "../type/jwtTypes";
|
||||||
import InternalException from "../exceptions/internalException";
|
import InternalException from "../exceptions/internalException";
|
||||||
import RefreshCommandHandler from "../command/refreshCommandHandler";
|
import RefreshCommandHandler from "../command/refreshCommandHandler";
|
||||||
import { CreateRefreshCommand } from "../command/refreshCommand";
|
import { CreateRefreshCommand } from "../command/refreshCommand";
|
||||||
|
@ -10,6 +10,8 @@ import UnauthorizedRequestException from "../exceptions/unauthorizedRequestExcep
|
||||||
import QRCode from "qrcode";
|
import QRCode from "qrcode";
|
||||||
import { CreateUserCommand } from "../command/userCommand";
|
import { CreateUserCommand } from "../command/userCommand";
|
||||||
import UserCommandHandler from "../command/userCommandHandler";
|
import UserCommandHandler from "../command/userCommandHandler";
|
||||||
|
import RefreshService from "../service/refreshService";
|
||||||
|
import BadRequestException from "../exceptions/badRequestException";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Check authentication status by token
|
* @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> {
|
export async function refresh(req: Request, res: Response): Promise<any> {
|
||||||
let token = req.body.token;
|
let token = req.body.token;
|
||||||
let refresh = req.body.refresh;
|
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,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
26
src/service/refreshService.ts
Normal file
26
src/service/refreshService.ts
Normal 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");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue