Browse Source

Feature: Implement token validation middleware with Redis caching and enhance error handling

emrecevik106 1 month ago
parent
commit
a18258e628
4 changed files with 87 additions and 13 deletions
  1. 14 0
      src/config/redis.ts
  2. 60 8
      src/middlewares/authMiddleware.ts
  3. 12 4
      src/routes/authRoutes.ts
  4. 1 1
      tsconfig.json

+ 14 - 0
src/config/redis.ts

@@ -0,0 +1,14 @@
+import Redis from "ioredis";
+
+export const redis = new Redis({
+    host: process.env.REDIS_HOST || "localhost",
+    port: Number(process.env.REDIS_PORT) || 6379,
+});
+
+redis.on("connect", () => {
+    console.log("Redis Connected");
+});
+
+redis.on("error", (error) => {
+    console.error("Redis connection error:", error);
+});

+ 60 - 8
src/middlewares/authMiddleware.ts

@@ -2,30 +2,82 @@ import {
     Request, Response, NextFunction 
 } from "express";
 import jwt from "jsonwebtoken";
+import {
+    redis 
+} from "../config/redis";
+import {
+    User 
+} from "../models/User";
 
 export interface AuthRequest extends Request {
     userId?: string;
+    context?: {
+        userId: string;
+        token: string;
+    };
 }
 
-export const authMiddleware = (req: AuthRequest, res: Response, next: NextFunction): void => {
+export const authMiddleware = async (req: AuthRequest, res: Response, next: NextFunction): Promise<void> => {
     try {
-        const authHeader = req.headers.authorization;
+        const token = req.headers.authorization;
 
-        if (!authHeader || !authHeader.startsWith("Bearer ")) {
+        if (!token) {
             res.status(401).json({
-                success: false, message: "Token bulunamadı" 
+                message: "token-not-found",
+                code: 401
             });
             return;
         }
 
-        const token = authHeader.split(" ")[1];
-        const decoded = jwt.verify(token, process.env.JWT_SECRET as string) as { userId: string };
+        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;
+        }
 
-        req.userId = decoded.userId;
+        if (!decoded || !decoded.userId) {
+            res.status(401).json({
+                message: "invalid-token",
+                code: 401
+            });
+            return;
+        }
+
+        const cachedToken = await redis.get(`user:${decoded.userId}`);
+        if (!cachedToken) {
+            res.status(401).json({
+                message: "expired-token",
+                code: 401
+            });
+            return;
+        }
+
+        if (cachedToken !== token) {
+            res.status(401).json({
+                message: "invalid-token",
+                code: 401
+            });
+            return;
+        }
+
+        const user = await User.findById(decoded.userId);
+        if (!user) {
+            res.status(401).json({
+                message: "user-not-found",
+                code: 401
+            });
+            return;
+        }
         next();
     } catch (error) {
         res.status(401).json({
-            success: false, message: "Geçersiz token" 
+            message: "invalid-token",
+            code: 401
         });
     }
 };

+ 12 - 4
src/routes/authRoutes.ts

@@ -1,14 +1,22 @@
 import {
-    Router
+    Router 
 } from "express";
 import {
-    register,
-    login
+    register, login 
 } from "../controllers/authController";
+import {
+    authMiddleware 
+} from "../middlewares/authMiddleware";
 
 const router = Router();
-
 router.post("/register", register);
 router.post("/login", login);
 
+router.get("/validate-token", authMiddleware, (req, res) => {
+    console.log("asasaas yüklendi");
+    res.status(200).json({
+        code: 200, message: "token-valsid",test:"merhaba"
+    });
+});
+
 export default router;

+ 1 - 1
tsconfig.json

@@ -105,6 +105,6 @@
     // "skipDefaultLibCheck": true,                      /* Skip type checking .d.ts files that are included with TypeScript. */
     "skipLibCheck": true,
     "experimentalDecorators": true,
-    "emitDecoratorMetadata": true                        /* Skip type checking all .d.ts files. */
+    "emitDecoratorMetadata": true                      /* Skip type checking all .d.ts files. */
   }
 }