0

I am working on a multi-step registration process and I am having an issue right now. What I am trying to achieve is to have a first call sending the information needed for the user to register, so to create him and logging him in, and then to ask him to update the previously randomly generated password on a second step. Everything is done using AJAX and the Wordpress REST API so there is no page reload. What I observe is that my step number one is properly generating a user and logging him using this code:

$password = wp_generate_password();
$userdata = array(
      'user_login'   => $email,
      'user_email'   => $email,
      'user_pass'    => $password,
      'display_name' => $firstname . ' ' . $name,
      'first_name'   => $firstname,
      'last_name'    => $name,
      'role'         => 'subscriber',
      'user_registered' => (new \DateTime())->format('Y-m-d H:i:s')
);
$user_id = wp_insert_user( $userdata ) ;

// Autologin after registration
wp_set_current_user($user_id);
if (wp_validate_auth_cookie()==FALSE)
{
     wp_set_auth_cookie($user_id, true, false);
}

But calling either wp_get_current_user or global $current_user during the additional step in order to update the generated password is retrieving only 0. Code:

$response = null;
$current_user = wp_get_current_user();
var_dump( $current_user );

Return:

object(WP_User)#3217 (7) {
 ["data"]=>
   object(stdClass)#3218 (0) {
   }
 ["ID"]=>
   int(0)
 ["caps"]=>
   array(0) {
   }
 ["cap_key"]=>
   NULL
 ["roles"]=>
   array(0) {
   }
 ["allcaps"]=>
   array(0) {
   }
 ["filter"]=>
   NULL

}

Do you have any idea why ? Is that normal behaviour ? For information, I am using cookie authentication as the Javascript code calling my user API is embedded in my custom theme.

Thanks in advance,

  • Can you check that the cookie set in the first AJAX response is being sent back in the second AJAX request? (i.e. browser > inspect > network) – TheDeadMedic Sep 5 '16 at 17:36
  • sounds like WP doesnt have the data yet. normally you would query WP User on init or later action, else your objects will still be empty – The J Sep 5 '16 at 17:59
  • Will check the two possibilitites, and let you know. Thanks ! – Balessan Sep 6 '16 at 8:24
  • In my opinion its not holding user_pass anywhere – seot Sep 6 '16 at 11:51
  • Cookies are properly sent, but the issue is related to authentication actually. A nonce generated on step 1 is not matching the evaluation of itself on step 2, and this behaviour is coming from a difference in the session tokens values. Even though wp_set_auth_cookie is used, the session token used to forge the nonce at step 1 is the same as the unlogged users previous step. So I guess I have to find a way to regerenate the sessiion token before calling the wp_create_nonce right after the registration fires. Tricky one. – Balessan Sep 6 '16 at 13:22
2

After a whole day of digging and debugging through the super duper Wordpress core functions, I realized the primary issue was that the session token used to create versus to verify the nonces were not equivalent. I tried different things, ending up calling the wp_set_auth_cookie method specifying the 'logged_in' cookie target.

Then, I fell on this topic: Extend Wordpress (4.x) session and nonce where the guy seems to have a problem similar to mine.

I gave it a shot, adding the following action in my class:

/**
 * login_force_update_cookie - Specific action for force overriding the logged_in_cookie
 * when being in the AJAX registration context
 *
 * @param  {type} $logged_in_cookie description
 * @return {type}                   description
 */
public function login_force_update_cookie( $logged_in_cookie ) {
  if ( strstr( $_SERVER['REQUEST_URI'], 'toto/user/register' ) ) {
    $_COOKIE[LOGGED_IN_COOKIE] = $logged_in_cookie;
  }
}

And modifying a bit my code which now looks like the following:

wp_set_current_user($user_id);
if ( wp_validate_auth_cookie( '', 'logged_in' ) != $user_id )
{
   wp_set_auth_cookie( $user_id );
}

// Storing the regitration event for the user
$this->saveLoginEvent( $user_id );
$data = array(
   'user_id' => $user_id,
   'nonce'   => wp_create_nonce( 'wp_rest' ),
   'message' => 'user_created'
);
$response = rest_ensure_response( $data );

And that seems to have fixed the main issue, being the inconsistency between the nonces generated in the first AJAX response and verified during the second one. The issue with the wp_get_current_user returning 0 was that when the nonces are not ok, wordpress is setting the user to 0 by default.

Quite a tricky one, made my day as I learned a lot !

Thanks for your attention,

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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