diff --git a/backend/app/Controllers/AuthController.php b/backend/app/Controllers/AuthController.php index 017ec86..6f6032f 100644 --- a/backend/app/Controllers/AuthController.php +++ b/backend/app/Controllers/AuthController.php @@ -327,10 +327,10 @@ class AuthController // 30 days token expiry $token = Security::generateJWT($payload, 30 * 86400); - // Single Session Enforcement: Store active session in Redis + // Single Session Enforcement: Store active session in Redis (Role-isolated) try { $redis = RedisClient::getInstance(); - $sessionKey = "active_session:{$userId}"; + $sessionKey = "active_session:{$role}:{$userId}"; $redis->setex($sessionKey, 30 * 86400, json_encode([ 'token_signature' => substr($token, -32), 'device_fingerprint' => $deviceFingerprint, @@ -657,10 +657,12 @@ class AuthController public function logout(Request $request, Response $response): void { $userId = $request->user_id; + $role = $request->role ?? 'student'; if ($userId) { try { $redis = RedisClient::getInstance(); - $redis->del("active_session:{$userId}"); + $redis->del("active_session:{$role}:{$userId}"); + $redis->del("active_session:{$userId}"); // Clean up legacy key if present } catch (\Exception $e) { error_log("Logout Redis error: " . $e->getMessage()); } diff --git a/backend/app/Middlewares/AuthMiddleware.php b/backend/app/Middlewares/AuthMiddleware.php index 5707082..0b7566b 100644 --- a/backend/app/Middlewares/AuthMiddleware.php +++ b/backend/app/Middlewares/AuthMiddleware.php @@ -36,11 +36,12 @@ class AuthMiddleware } $userId = (int)$payload['user_id']; + $role = (string)($payload['role'] ?? 'student'); - // Check if session is active in Redis (Single Active Device / Session Tracking) + // Check if session is active in Redis (Role-isolated single active session tracking) try { $redis = RedisClient::getInstance(); - $sessionData = $redis->get("active_session:{$userId}"); + $sessionData = $redis->get("active_session:{$role}:{$userId}") ?: $redis->get("active_session:{$userId}"); if ($sessionData) { $session = json_decode($sessionData, true);