Session expiry prevents logout if remember cookie exists
The remember token allows the user to authenticate without entering credentials indefinitely (i.e. 5 years) or until the user logs out.
However, if a session expires (can test with session lifetime of 1), then the user clicks log out, the remember cookie seems to log the user back in and the session is regenerated. So, on an expired session, if there is a remember cookie present, logging out does not remove the remember cookie.
Is this working as intended?
It doesn't seem right that a user could click 'logout' after the session expires and the result is that the user's session is refreshed and the remember cookie is not removed.
Thanks @jlrdw, it does log them out if the session is not expired.
I've followed the docs closely for my project so I don't think I've diverged. Maybe I'll create a fresh project and reproduce it before creating an issue.
Update: It seems to be an issue with Laravel. I created a fresh project, added auth, created user and logged in. I logged out to verify it worked correctly and saw the remember token get removed. I changed the session lifetime to 1, logged in, waited a minute and then logged out. This yielded a 'session expired' page so I navigated to the homepage, and unfortunately, I was still logged in and the remember token was still there.
This is normal and expected behavior as far as I can understand your situation.
The thing is that as soon as you click logout you are not being logged out because you were already logged out because your session expired. So the logout method is never executed and that is why the remember cookie is still available.
I agree that the framework is behaving as expected. However, it is a strange user experience to click 'logout' only to find you haven't been logged out and the remember cookie still exists.
Any thoughts on how to resolve that? Maybe expire the page somehow when the session expires?
I think the reason I am seeing this as a problem is because I auto-regenerate the expired session for the user. So, when the user clicks logout (after session expiry), it simply refreshes the page. For the user, this seems like nothing happened which is the desired behavior for all routes except logout.
I think the solution is to rework my project to just show a 'session expired page' on session expiration. Maybe I can work it to regenerate a session for all routes except logout.
You could also overwrite the logout method in the LoginController and clear the cookie yourself in that method regardless if the user is logged in or not.
In code it should look something like:
LoginController.php
public funciton __construct()
{
$this->middleware('guest');
// was: $this->middleware('guest', ['except' => 'logout']);
// this makes sure that a guest is also able to logout
}
public function logout(Request $request)
{
// if a user is logged in follow the default laravel logout logic
if (\Auth::check()) {
return parent::logout($request);
}
// if user is already logged out force remove the remember cookie
$cookie = \Cookie::forget('cookie_name_here');
return response()->redirectTo('/')->withCookie($cookie);
}
I did not test this and you need to set the correct cookie name.
I initially tried deleting the cookie in an overridden logout method but it didn't work. Not really sure why.
I don't have my code with me, but I believe I used the following to get the cookie name:
$cookie_name = Auth::getRecallerName();
It returned the correct cookie name but the cookie wasn't deleted. It seemed like it wasn't actually executing the logout method since the session was expired.
public function __construct()
{
$this->middleware('guest');
// $this->middleware('guest')->except('logout');
}
makes logout() non-functional if session is active. I inserted a dd() at the beginning of logout() to verify it never makes it there. The page just refreshes...not sure how to find the 'guest' middleware. Maybe it's related to the RedirectIfAuthenticated middleware? Obviously I need a better understanding of how auth is really working.
public function render($request, Exception $exception)
{
if ($exception instanceof \Illuminate\Session\TokenMismatchException) {
session()->flash('expiredSession', 'null');
return redirect()
->back()
->withInput($request->except('_token'));
}
return parent::render($request, $exception);
}
This caused the page to simply reload when clicking logout after session expiration. Normally, the exception is thrown so a user understands they need to refresh in order to logout. Thanks everybody for the help.