|
@@ -6,46 +6,73 @@ import redis from "../config/redis";
|
|
|
import {
|
|
import {
|
|
|
User
|
|
User
|
|
|
} from "../models/User";
|
|
} from "../models/User";
|
|
|
-
|
|
|
|
|
export interface AuthRequest extends Request {
|
|
export interface AuthRequest extends Request {
|
|
|
- userId?: string;
|
|
|
|
|
- token?: string;
|
|
|
|
|
|
|
+ context?: {
|
|
|
|
|
+ userId: string;
|
|
|
|
|
+ token: string;
|
|
|
|
|
+ };
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
export const authMiddleware = async (req: AuthRequest, res: Response, next: NextFunction): Promise<void> => {
|
|
export const authMiddleware = async (req: AuthRequest, res: Response, next: NextFunction): Promise<void> => {
|
|
|
try {
|
|
try {
|
|
|
- const authHeader = req.headers.authorization;
|
|
|
|
|
|
|
+ const token = req.headers.authorization;
|
|
|
|
|
|
|
|
- if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
|
|
|
|
|
+ if (!token) {
|
|
|
res.status(401).json({
|
|
res.status(401).json({
|
|
|
- message: "Token not found",
|
|
|
|
|
- code: 401
|
|
|
|
|
|
|
+ message: "token-not-found", code: 401
|
|
|
});
|
|
});
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const token = authHeader.split(" ")[1];
|
|
|
|
|
|
|
+ let decoded: { userId: string };
|
|
|
|
|
+ try {
|
|
|
|
|
+ decoded = jwt.verify(token, process.env.JWT_SECRET as string) as { userId: string };
|
|
|
|
|
+ } catch (err) {
|
|
|
|
|
+ res.status(401).json({
|
|
|
|
|
+ message: "expired-token", code: 401
|
|
|
|
|
+ });
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- const isBlacklisted = await redis.get(`bl_${token}`);
|
|
|
|
|
|
|
+ if (!decoded || !decoded.userId) {
|
|
|
|
|
+ res.status(401).json({
|
|
|
|
|
+ message: "invalid-token", code: 401
|
|
|
|
|
+ });
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (isBlacklisted) {
|
|
|
|
|
|
|
+ const cachedToken = await redis.get(`user:${decoded.userId}`);
|
|
|
|
|
+ if (!cachedToken) {
|
|
|
res.status(401).json({
|
|
res.status(401).json({
|
|
|
- message: "Your session has ended, please log in again.",
|
|
|
|
|
- code: 401
|
|
|
|
|
|
|
+ message: "expired-token", code: 401
|
|
|
});
|
|
});
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const decoded = jwt.verify(token, process.env.JWT_SECRET as string) as { userID: string };
|
|
|
|
|
|
|
+ if (cachedToken !== token) {
|
|
|
|
|
+ res.status(401).json({
|
|
|
|
|
+ message: "invalid-token", code: 401
|
|
|
|
|
+ });
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- req.userId = decoded.userID;
|
|
|
|
|
- req.token = token;
|
|
|
|
|
|
|
+ const user = await User.findById(decoded.userId);
|
|
|
|
|
+ if (!user) {
|
|
|
|
|
+ res.status(401).json({
|
|
|
|
|
+ message: "user-not-found", code: 401
|
|
|
|
|
+ });
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ req.context = {
|
|
|
|
|
+ userId: decoded.userId,
|
|
|
|
|
+ token: token
|
|
|
|
|
+ };
|
|
|
next();
|
|
next();
|
|
|
|
|
+
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
res.status(401).json({
|
|
res.status(401).json({
|
|
|
- message: "Invalid or expired tokens",
|
|
|
|
|
- code: 401
|
|
|
|
|
|
|
+ message: "invalid-token", code: 401
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|