Add token blacklist check in JWT middlewares to enhance session management and security
This commit is contained in:
@@ -49,6 +49,17 @@ export async function verifyHostToken(token: string): Promise<{ id: number; role
|
|||||||
include: { role: true },
|
include: { role: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const latestToken = await prisma.token.findFirst({
|
||||||
|
where: {
|
||||||
|
userXid: userId
|
||||||
|
},
|
||||||
|
orderBy: { id: 'desc' }
|
||||||
|
})
|
||||||
|
|
||||||
|
if (latestToken.isBlackListed == true) {
|
||||||
|
throw new ApiError(401, "This session is expired. Please login.")
|
||||||
|
}
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new ApiError(httpStatus.UNAUTHORIZED, 'User not found');
|
throw new ApiError(httpStatus.UNAUTHORIZED, 'User not found');
|
||||||
}
|
}
|
||||||
@@ -89,7 +100,7 @@ const verifyCallback = async (
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const userInfo = await verifyHostToken(token);
|
const userInfo = await verifyHostToken(token);
|
||||||
|
|
||||||
// Attach user to request
|
// Attach user to request
|
||||||
req.user = { id: userInfo.id.toString(), role: userInfo.role };
|
req.user = { id: userInfo.id.toString(), role: userInfo.role };
|
||||||
|
|
||||||
@@ -104,12 +115,12 @@ const verifyCallback = async (
|
|||||||
*/
|
*/
|
||||||
const authForHost =
|
const authForHost =
|
||||||
() =>
|
() =>
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
verifyCallback(req, resolve, reject);
|
verifyCallback(req, resolve, reject);
|
||||||
})
|
})
|
||||||
.then(() => next())
|
.then(() => next())
|
||||||
.catch((err) => next(err));
|
.catch((err) => next(err));
|
||||||
};
|
};
|
||||||
|
|
||||||
export default authForHost;
|
export default authForHost;
|
||||||
|
|||||||
@@ -49,6 +49,17 @@ export async function verifyMinglarAdminToken(token: string): Promise<{ id: numb
|
|||||||
include: { role: true },
|
include: { role: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const latestToken = await prisma.token.findFirst({
|
||||||
|
where: {
|
||||||
|
userXid: userId
|
||||||
|
},
|
||||||
|
orderBy: { id: 'desc' }
|
||||||
|
})
|
||||||
|
|
||||||
|
if (latestToken.isBlackListed == true) {
|
||||||
|
throw new ApiError(401, "This session is expired. Please login.")
|
||||||
|
}
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new ApiError(httpStatus.UNAUTHORIZED, 'User not found');
|
throw new ApiError(httpStatus.UNAUTHORIZED, 'User not found');
|
||||||
}
|
}
|
||||||
@@ -62,7 +73,7 @@ export async function verifyMinglarAdminToken(token: string): Promise<{ id: numb
|
|||||||
if (![ROLE.MINGLAR_ADMIN, ROLE.CO_ADMIN, ROLE.ACCOUNT_MANAGER].includes(user.roleXid)) {
|
if (![ROLE.MINGLAR_ADMIN, ROLE.CO_ADMIN, ROLE.ACCOUNT_MANAGER].includes(user.roleXid)) {
|
||||||
throw new ApiError(httpStatus.FORBIDDEN, 'Access denied.');
|
throw new ApiError(httpStatus.FORBIDDEN, 'Access denied.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return { id: user.id, role: user.role?.roleName };
|
return { id: user.id, role: user.role?.roleName };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -90,7 +101,7 @@ const verifyCallback = async (
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const userInfo = await verifyMinglarAdminToken(token);
|
const userInfo = await verifyMinglarAdminToken(token);
|
||||||
|
|
||||||
// Attach user to request
|
// Attach user to request
|
||||||
req.user = { id: userInfo.id.toString(), role: userInfo.role };
|
req.user = { id: userInfo.id.toString(), role: userInfo.role };
|
||||||
|
|
||||||
@@ -105,12 +116,12 @@ const verifyCallback = async (
|
|||||||
*/
|
*/
|
||||||
const authForHost =
|
const authForHost =
|
||||||
() =>
|
() =>
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
verifyCallback(req, resolve, reject);
|
verifyCallback(req, resolve, reject);
|
||||||
})
|
})
|
||||||
.then(() => next())
|
.then(() => next())
|
||||||
.catch((err) => next(err));
|
.catch((err) => next(err));
|
||||||
};
|
};
|
||||||
|
|
||||||
export default authForHost;
|
export default authForHost;
|
||||||
|
|||||||
@@ -51,6 +51,17 @@ export async function verifyMinglarAdminHostToken(token: string): Promise<{ id:
|
|||||||
include: { role: true },
|
include: { role: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const latestToken = await prisma.token.findFirst({
|
||||||
|
where: {
|
||||||
|
userXid: userId
|
||||||
|
},
|
||||||
|
orderBy: { id: 'desc' }
|
||||||
|
})
|
||||||
|
|
||||||
|
if (latestToken.isBlackListed == true) {
|
||||||
|
throw new ApiError(401, "This session is expired. Please login.")
|
||||||
|
}
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new ApiError(httpStatus.UNAUTHORIZED, 'User not found');
|
throw new ApiError(httpStatus.UNAUTHORIZED, 'User not found');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,17 @@ export async function verifyOnlyMinglarAdminToken(token: string): Promise<{ id:
|
|||||||
include: { role: true },
|
include: { role: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const latestToken = await prisma.token.findFirst({
|
||||||
|
where: {
|
||||||
|
userXid: userId
|
||||||
|
},
|
||||||
|
orderBy: { id: 'desc' }
|
||||||
|
})
|
||||||
|
|
||||||
|
if (latestToken.isBlackListed == true) {
|
||||||
|
throw new ApiError(401, "This session is expired. Please login.")
|
||||||
|
}
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new ApiError(httpStatus.UNAUTHORIZED, 'User not found');
|
throw new ApiError(httpStatus.UNAUTHORIZED, 'User not found');
|
||||||
}
|
}
|
||||||
@@ -62,7 +73,7 @@ export async function verifyOnlyMinglarAdminToken(token: string): Promise<{ id:
|
|||||||
if (user.roleXid !== ROLE.MINGLAR_ADMIN) {
|
if (user.roleXid !== ROLE.MINGLAR_ADMIN) {
|
||||||
throw new ApiError(httpStatus.FORBIDDEN, 'Access denied.');
|
throw new ApiError(httpStatus.FORBIDDEN, 'Access denied.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return { id: user.id, role: user.role?.roleName };
|
return { id: user.id, role: user.role?.roleName };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -90,7 +101,7 @@ const verifyCallback = async (
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const userInfo = await verifyOnlyMinglarAdminToken(token);
|
const userInfo = await verifyOnlyMinglarAdminToken(token);
|
||||||
|
|
||||||
// Attach user to request
|
// Attach user to request
|
||||||
req.user = { id: userInfo.id.toString(), role: userInfo.role };
|
req.user = { id: userInfo.id.toString(), role: userInfo.role };
|
||||||
|
|
||||||
@@ -105,12 +116,12 @@ const verifyCallback = async (
|
|||||||
*/
|
*/
|
||||||
const authForHost =
|
const authForHost =
|
||||||
() =>
|
() =>
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
verifyCallback(req, resolve, reject);
|
verifyCallback(req, resolve, reject);
|
||||||
})
|
})
|
||||||
.then(() => next())
|
.then(() => next())
|
||||||
.catch((err) => next(err));
|
.catch((err) => next(err));
|
||||||
};
|
};
|
||||||
|
|
||||||
export default authForHost;
|
export default authForHost;
|
||||||
|
|||||||
@@ -50,6 +50,17 @@ export async function verifyUserToken(token: string): Promise<{ id: number; role
|
|||||||
include: { role: true },
|
include: { role: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const latestToken = await prisma.token.findFirst({
|
||||||
|
where: {
|
||||||
|
userXid: userId
|
||||||
|
},
|
||||||
|
orderBy: { id: 'desc' }
|
||||||
|
})
|
||||||
|
|
||||||
|
if (latestToken.isBlackListed == true) {
|
||||||
|
throw new ApiError(401, "This session is expired. Please login.")
|
||||||
|
}
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new ApiError(httpStatus.UNAUTHORIZED, 'User not found');
|
throw new ApiError(httpStatus.UNAUTHORIZED, 'User not found');
|
||||||
}
|
}
|
||||||
@@ -90,7 +101,7 @@ const verifyCallback = async (
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const userInfo = await verifyUserToken(token);
|
const userInfo = await verifyUserToken(token);
|
||||||
|
|
||||||
// Attach user to request
|
// Attach user to request
|
||||||
req.user = { id: userInfo.id.toString(), role: userInfo.role };
|
req.user = { id: userInfo.id.toString(), role: userInfo.role };
|
||||||
|
|
||||||
@@ -105,12 +116,12 @@ const verifyCallback = async (
|
|||||||
*/
|
*/
|
||||||
const authForHost =
|
const authForHost =
|
||||||
() =>
|
() =>
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
verifyCallback(req, resolve, reject);
|
verifyCallback(req, resolve, reject);
|
||||||
})
|
})
|
||||||
.then(() => next())
|
.then(() => next())
|
||||||
.catch((err) => next(err));
|
.catch((err) => next(err));
|
||||||
};
|
};
|
||||||
|
|
||||||
export default authForHost;
|
export default authForHost;
|
||||||
|
|||||||
@@ -53,6 +53,10 @@ export class TokenService {
|
|||||||
config.jwt.secret
|
config.jwt.secret
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await this.prisma.token.deleteMany({
|
||||||
|
where: { userXid: user_xid }
|
||||||
|
})
|
||||||
|
|
||||||
await this.prisma.token.create({
|
await this.prisma.token.create({
|
||||||
data: {
|
data: {
|
||||||
token: refreshToken.token,
|
token: refreshToken.token,
|
||||||
@@ -100,6 +104,10 @@ export class TokenService {
|
|||||||
config.jwt.secret
|
config.jwt.secret
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await this.prisma.token.deleteMany({
|
||||||
|
where: { userXid: user_xid }
|
||||||
|
})
|
||||||
|
|
||||||
await this.prisma.token.create({
|
await this.prisma.token.create({
|
||||||
data: {
|
data: {
|
||||||
token: refreshToken.token,
|
token: refreshToken.token,
|
||||||
|
|||||||
Reference in New Issue
Block a user