I'm implimenting a simple magic link login feature and I've got it working nicely, however when the user is redirected to the homepage after being logged in the is_user_logged_in() still returns false, even though the login cookie is being set (confirmed via devtools). If I then refresh the page or navigate to another page the is_user_logged_in() then returns true.
Below is my code, I've removed all of the auth validation logic for simplicity:
// add login link rewrite rule
add_action('init', function () {
add_rewrite_rule('login-link$', 'index.php?login_link=1', 'top');
});
// add login link query var
add_filter('query_vars', function ($query_vars) {
$query_vars[] = 'login_link';
return $query_vars;
});
// handle login link
add_action('parse_request', function (&$wp) {
if (array_key_exists('login_link', $wp->query_vars)) {
$user = // get user and validate hashed token from url...
// login user
wp_clear_auth_cookie();
wp_set_current_user($user->ID);
wp_set_auth_cookie($user->ID);
do_action('wp_login', $user->user_login, $user);
// redirect to home
wp_safe_redirect(home_url());
exit();
}
});
The call to is_user_logged_in() is then happening inside the footer.php template file:
<?php if (is_user_logged_in()) : ?>
<p>Logged in as <?php echo esc_html(wp_get_current_user()->user_email); ?></p>
<?php endif; ?>
My understanding is that the parse_request hook happens before the headers are sent, and the cookie is being saved in the browser, so I don't think that's the issue. Any ideas why this could be happening?
I'm implimenting a simple magic link login feature and I've got it working nicely, however when the user is redirected to the homepage after being logged in the is_user_logged_in() still returns false, even though the login cookie is being set (confirmed via devtools). If I then refresh the page or navigate to another page the is_user_logged_in() then returns true.
Below is my code, I've removed all of the auth validation logic for simplicity:
// add login link rewrite rule
add_action('init', function () {
add_rewrite_rule('login-link$', 'index.php?login_link=1', 'top');
});
// add login link query var
add_filter('query_vars', function ($query_vars) {
$query_vars[] = 'login_link';
return $query_vars;
});
// handle login link
add_action('parse_request', function (&$wp) {
if (array_key_exists('login_link', $wp->query_vars)) {
$user = // get user and validate hashed token from url...
// login user
wp_clear_auth_cookie();
wp_set_current_user($user->ID);
wp_set_auth_cookie($user->ID);
do_action('wp_login', $user->user_login, $user);
// redirect to home
wp_safe_redirect(home_url());
exit();
}
});
The call to is_user_logged_in() is then happening inside the footer.php template file:
<?php if (is_user_logged_in()) : ?>
<p>Logged in as <?php echo esc_html(wp_get_current_user()->user_email); ?></p>
<?php endif; ?>
My understanding is that the parse_request hook happens before the headers are sent, and the cookie is being saved in the browser, so I don't think that's the issue. Any ideas why this could be happening?
The issue arises because the is_user_logged_in() function relies on the authentication cookies being recognized by the WordPress request lifecycle. When you set the authentication cookies using wp_set_auth_cookie(), they are sent to the browser, but they are not yet available to the same request that initiated the cookie setting. The cookies will only be recognized on subsequent requests.
// Handle login link
add_action('parse_request', function (&$wp) {
if (array_key_exists('login_link', $wp->query_vars)) {
$user = // get user and validate hashed token from url...
// Log in the user
wp_clear_auth_cookie();
wp_set_current_user($user->ID);
wp_set_auth_cookie($user->ID);
// Set the global $current_user manually for the current request
global $current_user;
$current_user = $user;
do_action('wp_login', $user->user_login, $user);
// Redirect to home
wp_safe_redirect(home_url());
exit();
}
});
1).global $current_user; $current_user = $user;: This ensures that the global $current_user variable is set for the current request.
2). wp_set_current_user($user->ID);: Even though you've already set the user in wp_set_auth_cookie(), this ensures that WordPress internally knows about the current user for this request.
By doing this, is_user_logged_in() will correctly recognize the logged-in status for the current request.