1

I am currently working on a multi-steps registration system, based on the new Wordpress Rest API and I got an issue related to the nonce generation and verifying.

My first step is to ask the user from a frontend form for the essential information (name - firstname - email address). The second one is to ask him for additional metadata information. Then the third one to ask him for its password and password confirmation.

There are 3 different HTTP Post request in the process, everything is handled in AJAX. The strategy I applied is to generate a nonce on the server side if the first POST is ok, and to return it in the JSON response. Here is the code for the user creation at the first step:

 $user_id = wp_insert_user( $userdata ) ;          
 $user = new \WP_User($user_id);
 if (!empty( $user ) && $user instanceof \WP_User) {
    $user->add_role( 'subscriber' );
 }

 // Autologin after registration
 wp_set_current_user($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'
 );

The user is properly created and logged-in. But, using this nonce during the additional steps is considered invalid (always getting 403). My code for veryfying the nonce is the following:

/**
 * authenticate_call - Default permission callback used to validate that the call is coming from our frontend
 *
 * @return {WP_nonce}  The state of the nonce, if it is verified or not
 */
public function authenticate_call() {

   if ( isset( $_REQUEST['_wpnonce'] ) ) {
       $nonce = $_REQUEST['_wpnonce'];
   } elseif ( isset( $_SERVER['HTTP_X_WP_NONCE'] ) ) {
       $nonce = $_SERVER['HTTP_X_WP_NONCE'];
   }

   if ( empty( $nonce ) || null === $nonce ) {
     // No nonce at all, so act as if it's an unauthenticated request.
     return new \WP_Error( 'rest_cookie_no_nonce', __( 'Nonce is invalid' ), array( 'status' => 403 ) );
   }

   $result = wp_verify_nonce( $nonce, 'wp_rest' );
   if ( ! $result ) {
    return new \WP_Error( 'rest_cookie_invalid_nonce', __( 'Cookie nonce is invalid' ), array( 'status' => 403 ) );
   }

   return true;
}

The error I am getting is the second one: rest_cookie_invalid_nonce. The nonce is passed as URL parameter like this POST www/api/url?_wpnonce=a30e88f0bd. Any idea ? Do you know anything about an impossibility to have the backend generating the nonce and returning it to the frontend ? Should I generate it on the frontend using a method I don't know about yet. If it helps, I am using Timber and Twig as the frontend architecture components.

Thanks in advance,

1
  • The nonce is returned in the JSON response from the first POST request, as shown in the $data array in the first code block 'nonce' => wp_create_nonce( 'wp_rest' ),
    – Balessan
    Commented Sep 1, 2016 at 15:58

1 Answer 1

2

If anybody is strangling with it, the proper solution is to use both wp_set_auth_cookie specifying the second parameter being the logged_in cookie, which now gives me the following code:

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

And to add an action, as suggested in this thread: Extend Wordpress (4.x) session and nonce to have the logged-in current cookie properly overriden without needing a page refresh.

That was a tricky one for sure, and undocumented anywhere. Did anybody tried that yet ?

Thanks for your attention anyway,

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.