json([ 'success' => true, 'timeout' => SessionTimeout::TIMEOUT_DURATION, 'warning_time' => SessionTimeout::WARNING_THRESHOLD, 'check_interval' => SessionTimeout::CHECK_INTERVAL, 'logout_url' => url('/api/v1/auth/logout'), 'keep_alive_url' => url('/api/v1/session/pingActivity'), 'check_url' => url('/api/v1/session/checkTimeout'), ]); } public function checkTimeout(): JsonResponse { $session = session(); // Verify session exists and has last_activity if (!$session->has('last_activity')) { return $this->expireSession(); } $lastActivity = $session->get('last_activity'); $elapsed = time() - $lastActivity; if ($elapsed > SessionTimeout::TIMEOUT_DURATION) { return $this->expireSession(); } elseif ($elapsed > SessionTimeout::WARNING_THRESHOLD) { return response()->json([ 'status' => 'warning', 'time_remaining' => SessionTimeout::TIMEOUT_DURATION - $elapsed, ]); } return response()->json([ 'status' => 'active', 'time_remaining' => SessionTimeout::TIMEOUT_DURATION - $elapsed, ]); } public function pingActivity(): JsonResponse { $session = session(); // Only update if session is still valid if (!$session->has('last_activity') || (time() - $session->get('last_activity') > SessionTimeout::TIMEOUT_DURATION)) { return $this->expireSession(); } $session->put('last_activity', time()); return response()->json([ 'status' => 'active', 'time_remaining' => SessionTimeout::TIMEOUT_DURATION, ]); } private function expireSession(): JsonResponse { $this->destroySession(); return response()->json([ 'status' => 'expired', 'redirect' => url('/login'), 'message' => 'Your session has expired due to inactivity.', ], Response::HTTP_UNAUTHORIZED); } private function destroySession(): void { $session = session(); $session->flash('error', 'Your session has expired due to inactivity.'); // Clear session data $session->forget('last_activity'); $session->invalidate(); // Regenerate session ID for security $session->regenerate(true); } }