8

We've got a small web application that allows users to log in (via WordPress) and remain logged in for a max 15 min session for security purposes. Because most sessions will last longer, I have a small ajax call that's made on each click of the html document itself.

The ajax call itself fires to the /admin-ajax.php file, and it hits a function (in functions.php). Below is that function:

function extend_my_session_yo(){
    $user_id = get_current_user_id();
    wp_set_auth_cookie($user_id, false, true);

    $new_logout = wp_logout_url();

    if ( is_user_logged_in() ) {
        echo 'session extended 15 mins ' . $new_logout;
    } 
    // if a user is *not* logged in, Wordpress just outputs a "0". 
    die();
}

The wp_set_auth_cookie() does the hard work. It correctly allows for (on each click) an extended 15 mins session. The problem is if someone tries to logout. The current logout link is echo'd via wp_logout_url(), but that logout url has a nonce from the moment it's created by WordPress.

So in the function above, I'm generating a new logout url (and from the WP core code it seems that this is generated by getting the session token from the new cookie), but each click of the new logout url gives the Wordpress Failure Notice page indicating a nonce mismatch. I've even gone so far to copy code from pluggable.php (for wp_verify_nonce()) for checking the hash_equals() function for $expected vs $nonce and they're equal. Yet I still get nonce errors.

Does anyone know how to set a new auth/logged_in cookie while also setting a new nonce to avoid these errors?

4
  • I'm surprised the logout link for the original session doesn't work. Can you tie another AJAX function to your logout link that runs a function to invalidate the cookie immediately then on the callback redirect to your desired page? Commented Feb 28, 2015 at 3:07
  • @JasonMurray The original logout link is invalidated because the new cookies issued (via the ajax call) have different token info that changes the nonce interaction with the original logout url. I've thought about a new ajax call, or just redirecting to a page that calls wp_logout() (which invalidates all session cookies) but the fact is I also need the nonce/token issue solved for a page that allows for users to edit posts on the front end. That uses nonces, of course, so it's an issue I have to solve (and keep scratching my head with options I've tried).
    – MikeTT
    Commented Mar 2, 2015 at 1:18
  • Ok, after just reading the idea on your question: Why do you perform the action on every click when the time out should happen after 15 minutes of inactivity(?) and without a click? Why don't you push the original first login time() to the script and only perform the update when for e.g. 14 minutes passed? Keep in mind that every AJAX callback will load the entire WP core.
    – kaiser
    Commented Mar 4, 2015 at 0:29
  • @kaiser Indeed I thought about firing it after 14 mins as well, but the issue is that after I fire the AJAX call, I'll still run into this same issue. I do hear you on not necessarily wanting to load the entire core each click and so if I can get a solution for how to match the nonce and tokens for any time interval, I'll certainly optimize it to work only after 14 mins to optimize server resources. For now I've gone through as many WP core files I can to understand how it works and I'm left with the idea that it must be either 1.) really complex, or 2. something easy and obvious I'm missing.
    – MikeTT
    Commented Mar 5, 2015 at 17:04

1 Answer 1

8

Your problem is that you call wp_logout_url immediately after wp_set_auth_cookie.

wp_set_auth_cookie() does some setcookie() calls. Unfortunately setcookie doesn't make the new value available instantly in the PHP global $_COOKIE. It must be set through a new HTTP Request first.

wp_logout_url() (via wp_nonce_url > wp_create_nonce > wp_get_session_token > wp_parse_auth_cookie) fetches $_COOKIE[LOGGED_IN_COOKIE] in order to create a valid nonce, not knowing that the logged in cookie has already been updated. (I'm not quite sure if we may call this a WP core bug.)

There is an action hook in wp_set_auth_cookie named set_logged_in_cookie, which should allow you to update the session cookie value during your ajax request.

function my_update_cookie( $logged_in_cookie ){
    $_COOKIE[LOGGED_IN_COOKIE] = $logged_in_cookie;
}
add_action( 'set_logged_in_cookie', 'my_update_cookie' );
3
  • Thanks @Jörn. Are you saying that after I call wp_set_auth_cookie that I should call the my_update_cookie function (presumably via do_action('my_update_cookie'))?
    – MikeTT
    Commented Apr 14, 2015 at 19:45
  • Yes, this would be the simple solution. Alternatively you get the the logout_url in a second AJAX request (when the new cookie is available).
    – Jörn Lund
    Commented Apr 15, 2015 at 17:46
  • You're the man. Added it and the logout url works. I indicated your answer is correct though admittedly I still need to work on the WP core. Currently I limit the ajax feature above to the front-end, but there's a need to make this work in WP for editing/updating posts. Currently it won't work because of Nonce issues, and your solution helps me get closer to making that work as well.
    – MikeTT
    Commented Apr 17, 2015 at 20:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.