Asked 1 month ago by PlutonianCaptain585
How can I check for Laravel session expiration without inadvertently renewing it?
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
Asked 1 month ago by PlutonianCaptain585
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
I'm working on a Laravel/Inertia/Vue application and need to verify if the session has expired without updating its last_activity timestamp. If expired, a popup should be displayed. The current check is via a backend endpoint using the session database driver.
Below is the backend code (to be moved into a controller if needed):
PHPRoute::get('/session-status', function (\Illuminate\Http\Request $request) { $sessionId = cookie(config('session.cookie')); if (!\Illuminate\Support\Facades\Auth::check()) { return response()->json(['session_expired' => true], 401); } // Fetch session directly from the database (without updating last_activity) $sessionId = $request->session()->getId(); $session = \Illuminate\Support\Facades\DB::table('sessions') ->select('last_activity') ->where('id', $sessionId) ->first(); if ($session) { $sessionLifetime = config('session.lifetime') * 60; $sessionAge = now()->timestamp - $session->last_activity; if ($sessionAge > $sessionLifetime) { return response()->json(['session_expired' => true], 401); } } return response()->json(['session_expired' => false]); })->name('session.status');
On the frontend, a simple axios call is used to check the session status:
JAVASCRIPTconst showPopup = ref(false); const checkSession = async () => { try { await axios.get('/api/session-status'); } catch (error) { if (error.response && error.response.status === 401) { showPopup.value = true; } } }; // Run session check every 1 minute onMounted(() => { setInterval(checkSession, 6000); });
I have tried several approaches, but Laravel keeps updating the session when it is checked, which prevents natural expiration by continuously renewing the session. I'm seeking a solution that checks session expiry without altering its last_activity. Any ideas?
Comments 0
•Answers 2
•Views 53
Answer by TychoAI Agent • 1 month ago
Below is one proven approach: stop “touching” the session on your ping endpoint by not booting the session middleware (or at least not calling methods that update it) so your check is read-only. For example, instead of using the session instance and calling Auth::check() (which by its very nature will read from—and update—the session), you can do the following:
A sample route might look like this:
PHPuse Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Cookie; Route::get('/session-status', function (Request $request) { // Get the session ID directly from the cookie. $sessionId = Cookie::get(config('session.cookie')); if (!$sessionId) { // No session cookie? Treat as expired. return response()->json(['session_expired' => true], 401); } // Query the sessions table directly without loading the session. $session = DB::table('sessions') ->select('last_activity') ->where('id', $sessionId) ->first(); if ($session) { $sessionLifetime = config('session.lifetime') * 60; $sessionAge = now()->timestamp - $session->last_activity; if ($sessionAge > $sessionLifetime) { return response()->json(['session_expired' => true], 401); } } else { // No session record found, so treat as expired. return response()->json(['session_expired' => true], 401); } return response()->json(['session_expired' => false]); }) // Remove session middleware so this endpoint does not touch session data. ->withoutMiddleware([\Illuminate\Session\Middleware\StartSession::class]) ->name('session.status');
A few notes on this approach:
On the frontend your axios call remains the same:
JAVASCRIPTconst showPopup = ref(false); const checkSession = async () => { try { await axios.get('/api/session-status'); } catch (error) { if (error.response && error.response.status === 401) { showPopup.value = true; } } }; // Run session check every minute (60000 ms) onMounted(() => { setInterval(checkSession, 60000); });
With this design, your session’s last_activity is not updated by the check endpoint, so if a user truly becomes inactive the natural expiry will occur.
Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?
No comments yet.
Answer by MartianVoyager297 • 1 month ago
What you can do is you can create middleware because of which your session will not get inadvertently be live. As here whenever you checks the session it will keep it alive. As sessions are timeout when they are not used for particular period of time.
First create middleware
BASHphp artisan make:middleware CheckSession
Implement your whole logic like below
PHPnamespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; class CheckSession { public function handle($request, Closure $next) { if (!Auth::check()) { return response()->json(['session_expired' => true], 401); } $sessionId = $request->session()->getId(); $session = DB::table('sessions')->select('last_activity')->where('id', $sessionId)->first(); if ($session) { $sessionLifetime = config('session.lifetime') * 60; $sessionAge = now()->timestamp - $session->last_activity; if ($sessionAge > $sessionLifetime) { return response()->json(['session_expired' => true], 401); } } return $next($request); } }
Now register your Middleware in 'app/Http/Kernel.php'
PHPprotected $routeMiddleware = [ // ... 'check.session' => \App\Http\Middleware\CheckSession::class, ];
Now your route
PHPRoute::get('/session-status', function () { return response()->json(['session_expired' => false]); })->middleware('check.session')->name('session.status');
I hope this should work.
No comments yet.
No comments yet.