User()->logout() is not committed immediately

Hi,

If I execute this in the controller of my logout page:

user()->logout();

The following command returns still true in the page template (and user object exists):

user()->isLoggedIn();

User is logged out successfully though, but the logout page is rendered as if the user is still logged in. Tested in Kirby 3.2.5.

This used to work correctly before, but maybe the inner workings of the logout operation were changed in some update. If so, is it intentional that logout is not committed within the same page request?

Is that your real code? It doesn’t make sense, because there is no user() method.

Oh, that’s right, it’s a custom helper function. I’m so used to using it it that I forgot it’s not official.

function user()
{
	return kirby()->user();
}

You would have to store your logged out user in a variable though and pass that to your template.

Apart from that, you have to check if you have a user object before calling any of the user methods.

if ($user = user()) {
  echo $user->isLoggedIn();
}

The problem still persists. I created a reproducible example with starter-kit:

  1. Download and install starterkit-master (Kirby 3.2.5)
  2. Create a new page template called “logout” and a corresponding content page: content/logout/logout.txt
  3. Create an admin account in panel and log in
  4. Enter the newly created logout page localhost/logout

site/controllers/logout.php

<?php

return function($site, $pages, $page) 
{
	$user = kirby()->user();

	if ($user) {
		$user->logout();
	}
	
	return compact('user');
};

site/templates/logout.php

<?php

if ($user) {
	if ($user->isLoggedIn() == true)
		echo 'User is logged in';
	else
		echo 'User is logged out';
} else {
	echo "No user object";
}
?>

When I enter the page the first time while logged in, I get “User is logged in”, which shouldn’t be the case. The second time I get “No user object”, which is correct. Can you repeat the scenario and confirm if you get the same result?

What if you use:

if ($user) {
    $user = $user->logout();
}

Well, technically, that equals calling $user->logout() first and then setting $user = null, since logout has return type of void.

The thing is that I have a bunch of snippets, which help rendering each page, and the content of these snippets vary depending on whether the user is logged in or not. While it’s technically possible to piggy-bag the $user reference to each part responsible for rendering the page, I find it counter-intuitive that kirby()->user() cannot be trusted in this specific instance to reflect the current situation.

Also, I’m quite sure this used to work before. That’s why I’m wondering whether this is a regression bug or a deprecated feature.

Using the isLoggedIn() method doesn’t make sense anyway.

if ($user = $kirby->user()) {
  echo 'Yay, user is logged in';
}

is the way to check if the current site visitor is a logged in user.

isLoggedIn() however, only checks if the given user is the logged in user:

   public function isLoggedIn(): bool
    {
        return $this->is($this->kirby()->user());
    }

Yeah, maybe the method should be called something like isCurrentUser or similar.

Would be still nice to hear from devs if this is an oversight or something that is intended functionality.

In any case, I couldn’t reproduce your issue but only tested with 3.3.0 rc-3, not 3.2.5.

Can reproduce this issue with both 3.3.0 rc-3 and the newest rc-4.

You could create an issue on GitHub. But I’m not so sure this worked before, unless you reroute, which is usually the case if you log the user out.

And as I said before, if you assign $user->logout() to the $user variable, it works without issues.

But I might be wrong, so go ahead.

Sorry, I forgot to add one critical line to the template, no idea how that happened… So the template I used in the reproducable error was

site/templates/logout.php

<?php

$user = kirby()->user();

if ($user) {
	if ($user->isLoggedIn() == true)
		echo 'User is logged in';
	else
		echo 'User is logged out';
} else {
	echo "No user object";
}
?>

So the issue is that, even though I could follow your advice and assign $user to null in controller, and use that instead of kirby()->user(), any snippet or plugin in the template using kirby()->user() will still think user is logged in.

And I was able to confirm that this issue did not exist in Kirby version 3.1.4, so I think it’s worthwhile to submit the issue to Github.

Edit. Github issue: https://github.com/getkirby/kirby/issues/2267

For anyone interested, this issue has been addressed and will be fixed in Kirby 3.3.1

1 Like