Today I noticed something disturbing while inspecting session files in storage/framework/sessions
folder created by Laravel 5.
Here is what happened:
storage/framework/sessions
was still there, and browser
cookie was alive. storage/framework/sessions
got deleted and a new session file was there.It leads to security concerns because now user B has access to the data of user A.
While debugging through Laravel source code, I found out that Session Store is never being cleared up during logout/login process. Only login credentials are being removed in Illuminate\Auth\Guard::clearUserDataFromStorage()
method, but all the session Store attributes are still there, and then later when $kernel->terminate($request, $response);
is called, which in turn leads to Illuminate\Session\Middleware\StartSession::terminate()
calling Store::save()
, which blindly saves $this->attributes
to the new session, ignoring the fact that it now belongs to another user.
From one hand, it seems logical - Laravel has no assumptions about my data and whether I want it to expire together with authentication or not. But it would be great to have it documented somewhere with a solution to attach some sensitive data to authentication object and expire together with it.
This means that I as a programmer am responsible for completely clearing away all the sensitive data from current session when a new (or the same) user is logging in.
Clearing on logging out would not be reliable, because user might never click Logout link but wait for the session to "expire", which for Laravel still does not clear up the session.
One more thing to keep in mind: I should not clear the session too early - there is AntiForgery token which must be present, or else login form will always fail.
I have found a forum topic which also tries to solve somewhat similar problem:
http://laravel.io/forum/04-27-2014-how-to-expire-session-data
I got confused by this:
I had another go at it today and realised what the problem was: Session::flush() does not delete session data that the app creates, such as the shopping cart details
If this is true, then the only way to get completely rid of session would be to use PHP native session_unset()
and session_destroy()
but I wouldn't want to go that way - I would prefer to find a cleaner, Laravel-ish solution, if possible.
How do I tell Laravel that I want my old session data to be removed together with user authentication data when authentication expires or user logs out?
You need to understand what happened: You've set the lifetime of the sessions to 120 minutes, which means after 120 minutes the session is flushed. The remember_me feature is using cookies. If there is no user session Laravel checks the cookies and recreates the session if the session cookie is still valid.
Data can be stored in session using the put() method. The put() method will take two arguments, the “key” and the “value”.
Of course each user session is unique to that logged in user.
Laravel ships with several great drivers out of the box: file - sessions are stored in storage/framework/sessions . cookie - sessions are stored in secure, encrypted cookies. database - sessions are stored in a relational database.
In the laravel docs it says you can:
Removing An Item From The Session
Session::forget('key');
Removing All Items From The Session
Session::flush();
You could navigate to the AuthenticatesAndRegistersUsers.php trait and rewrite
/**
* Log the user out of the application.
*
* @return \Illuminate\Http\Response
*/
public function getLogout()
{
$this->auth->logout();
return redirect(property_exists($this, 'redirectAfterLogout') ? $this->redirectAfterLogout : '/');
}
to
/**
* Log the user out of the application.
*
* @return \Illuminate\Http\Response
*/
public function getLogout()
{
Session::flush();
$this->auth->logout();
return redirect(property_exists($this, 'redirectAfterLogout') ? $this->redirectAfterLogout : '/');
}
I have no idea if this actually work, but give it a try :)
Update
According to this answer here on Stack Overflow, you can set the session to expire on browser close, or after XXX minutes. Used together with the above solution, it should fix the problem?
In config/session.php
/*
|--------------------------------------------------------------------------
| Session Lifetime
|--------------------------------------------------------------------------
|
| Here you may specify the number of minutes that you wish the session
| to be allowed to remain idle before it expires. If you want them
| to immediately expire on the browser closing, set that option.
|
*/
'lifetime' => 120,
'expire_on_close' => false
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With