1
votes

TL;DR:

is_user_logged_in() always returns false when used by admin-ajax.

In Detail

So I'm trying to run a script on the client to display dynamic content based on whether a user is logged in or not. (So that I can serve static cached pages and still have some dynamic control over it).

The idea is this: Use javascript to hide/show certain content (like suggesting a login). This lets me leverage better caching services and serve compressed static pages while still being able to adjust the content of the page for users that are logged in. So, I'll use AJAX to ask the server if we're currently logged in, and if we are, we'll show/hide the appropriate content. The compressed static page will assume that we aren't logged in, but AJAX will check after the (super fast) page load and adjust things as needed.

Seems straight forward... Hook a custom AJAX function into init and kick back JSON data returned by the server so that the javascript knows if we're logged in or not.

Only issue is that all the wordpress functions used to do this return NULL, 0 or false.

functions.php The extra echo's are there for debugging wordpress action orders

function check_login_init() {
    add_action('wp_ajax_check_login', 'check_login');
    add_action('wp_ajax_nopriv_check_login', 'check_login');
}
add_action('init', 'check_login_init');
function check_login() {
    echo 'did init action: ' . (did_action( 'init' ) ? 'true' : 'false') . '<br />';
    echo 'did admin_init action: ' . (did_action( 'admin_init' ) ? 'true' : 'false') . '<br />';
    echo 'did set_current_user action: ' . (did_action( 'set_current_user' ) ? 'true' : 'false') . '<br />';
    echo 'did get_footer action: ' . (did_action( 'get_footer' ) ? 'true' : 'false') . '<br />';
    var_dump(wp_get_current_user());
    if (did_action( 'init' )) {
        if (is_user_logged_in()) {
            echo 'true';
        } else if (!is_user_logged_in()) {
            echo get_current_user_id();
        }
    } else {
        echo 'init did not execute, AJAX failed';
    }
    wp_die();
}

Sadly this returns the following:

Output

did init action: true
did admin_init action: true
did set_current_user action: true
did get_footer action: false
object(WP_User)#1917 (7) { ["data"]=> object(stdClass)#1918 (0) { } ["ID"]=> int(0) ["caps"]=> array(0) { } ["cap_key"]=> NULL ["roles"]=> array(0) { } ["allcaps"]=> array(0) { } ["filter"]=> NULL } 0

init, admin_init and set_current_user all proc as expected, and yet all the methods associated with having an authenticated user fail.

What I've tried so far

  • I've disabled all plugins associated with the admin panel and security
  • I've commented out all my own code that does the same
  • Reset .htaccess to the Wordpress default
  • Instantiated both global $current_user and global $wp from within the function
  • Ensured that no caching is occurring on the server nor the client
  • Disabled CDN through CloudFlare
1

1 Answers

0
votes

I had this issue as well, all ajax requests came though as if it was not signed in. It was resolved once the wp-config.php was setup correctly. If your using HTTPS and SSL but are behind a reverse proxy that forwards it as a HTTP request you would need to do something like this for it to work:

<?php
# ... Other config here ...
if($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
  define('WP_SITEURL', 'https://'.$_SERVER['HTTP_HOST']);
  define('WP_HOME',    'https://'.$_SERVER['HTTP_HOST']);
  # Without this WP think it should be on HTTPs, but it's not. Thus it creates a redirect loop
  $_SERVER['HTTPS']='on';
} else {
  define('WP_SITEURL', 'http://'.$_SERVER['HTTP_HOST']);
  define('WP_HOME',    'http://'.$_SERVER['HTTP_HOST']);
}

Note that the X-Forwarded-Proto header have to be set on your reverse proxy.