authentication - Rest API: wp_verify_nonce() fails despite receiving correct nonce value

I am generating a nonce to be used with client side fetch requests to the rest api:function prepAllAdminScripts() {wp_re

I am generating a nonce to be used with client side fetch requests to the rest api:

function prepAllAdminScripts() {
  wp_register_script(
    'reactAdminArea'
    , PLUGIN_FOLDER_URL . 'shared/adminArea.bundle.js'
    , null
    , null
    , true
  );

  wp_localize_script('reactAdminArea', 'serverParams', [
    '_wpnonce' => wp_create_nonce('wp_rest')
    , 'apiBaseUrlFromWp' => get_rest_url()
  ]);

  wp_enqueue_script('reactAdminArea');
}
add_action('admin_enqueue_scripts', 'prepAllAdminScripts');

As the fetch request is fired, I see it go into an auth handler function. The nonce value shows as a string and appears to be a matching nonce value but it fails:

  protected function authUserOrRespondWithError($clientNonce) { // 3a730<partially removed>
    $verification = wp_verify_nonce($clientNonce); // false

    if ($verification === false) {
      wp_send_json(['error' => "Failed nonce verification"]); // sends back to the client
    }
  }

When I check the nonce value in the Chrome browser console, it matches exactly.

Does anyone know why the verification is returning false here?

Update

Here is how I am sending the nonce data back to the API:

const fetchAllCoupons = async () => {
    try {
      const response = await fetch(`${apiBaseUrl}/pluginFolder/1.0/loadAll`, {
        method : 'post',
        headers : {
          'Content-Type' : 'application/json'
        },
        body : JSON.stringify({clientNonce})
      });
      let data = await response.json();

      if (data && 'error' in data) {
        setSnackbarMessage(data.error)
      }

      return data;
    }
    catch (e) {
      console.log(e, `=====error=====`);
    }
  };

Here is the route handler:

  public function registerLoadCouponRoute() : void {
    register_rest_route($this->urlBase, 'loadAll', [
      'methods' => ['get', 'post'],
      'callback' => [$this, 'respondAllCoupons']
    ]);
  }

Here is the first part of the callback that contains authUserOrRespondWithError:

  public function respondAllCoupons(\WP_REST_Request $request) {
    global $wpdb;

    $clientNonce = $request->get_param('clientNonce');
    $this->authUserOrRespondWithError($clientNonce);

I am generating a nonce to be used with client side fetch requests to the rest api:

function prepAllAdminScripts() {
  wp_register_script(
    'reactAdminArea'
    , PLUGIN_FOLDER_URL . 'shared/adminArea.bundle.js'
    , null
    , null
    , true
  );

  wp_localize_script('reactAdminArea', 'serverParams', [
    '_wpnonce' => wp_create_nonce('wp_rest')
    , 'apiBaseUrlFromWp' => get_rest_url()
  ]);

  wp_enqueue_script('reactAdminArea');
}
add_action('admin_enqueue_scripts', 'prepAllAdminScripts');

As the fetch request is fired, I see it go into an auth handler function. The nonce value shows as a string and appears to be a matching nonce value but it fails:

  protected function authUserOrRespondWithError($clientNonce) { // 3a730<partially removed>
    $verification = wp_verify_nonce($clientNonce); // false

    if ($verification === false) {
      wp_send_json(['error' => "Failed nonce verification"]); // sends back to the client
    }
  }

When I check the nonce value in the Chrome browser console, it matches exactly.

Does anyone know why the verification is returning false here?

Update

Here is how I am sending the nonce data back to the API:

const fetchAllCoupons = async () => {
    try {
      const response = await fetch(`${apiBaseUrl}/pluginFolder/1.0/loadAll`, {
        method : 'post',
        headers : {
          'Content-Type' : 'application/json'
        },
        body : JSON.stringify({clientNonce})
      });
      let data = await response.json();

      if (data && 'error' in data) {
        setSnackbarMessage(data.error)
      }

      return data;
    }
    catch (e) {
      console.log(e, `=====error=====`);
    }
  };

Here is the route handler:

  public function registerLoadCouponRoute() : void {
    register_rest_route($this->urlBase, 'loadAll', [
      'methods' => ['get', 'post'],
      'callback' => [$this, 'respondAllCoupons']
    ]);
  }

Here is the first part of the callback that contains authUserOrRespondWithError:

  public function respondAllCoupons(\WP_REST_Request $request) {
    global $wpdb;

    $clientNonce = $request->get_param('clientNonce');
    $this->authUserOrRespondWithError($clientNonce);
Share Improve this question edited Sep 8, 2019 at 9:57 Sean D asked Sep 5, 2019 at 21:45 Sean DSean D 3878 silver badges21 bronze badges 2
  • 1 How are you sending the nonce? From the URL as a query param and how you capture it in your REST API? – Roel Magdaleno Commented Sep 6, 2019 at 0:00
  • @RoelMagdaleno I send it in the post body of a fetch request. I have updated the original post to show the request handler. I capture it with a rest route handler using the callback shown. As mentioned, I can see the value arrives and is correct – Sean D Commented Sep 6, 2019 at 6:59
Add a comment  | 

1 Answer 1

Reset to default 2

First, nonce for an action is the same when the user is not authenticated/logged-in. (because the user ID is always 0)

Secondly, you're getting false because you didn't specify the nonce action which is wp_rest in your case:

// Correct usage - a valid action name is set (wp_rest).
wp_verify_nonce( $clientNonce, 'wp_rest' );

// Incorrect usage - empty action; always returns false.
wp_verify_nonce( $clientNonce );

And if you are actually trying to authenticate the request using the standard cookie authentication, then you should use the X-WP-Nonce header to send the nonce and not the request body/payload:

const fetchAllCoupons = async () => {
  try {
    const response = await fetch(`${apiBaseUrl}/pluginFolder/1.0/loadAll`, {
      method: 'post',
      headers: {
        'Content-Type': 'application/json',
        'X-WP-Nonce': clientNonce // <- here, send the nonce via the header
      },
      body: JSON.stringify({
        // WordPress will not use this when verifying the associated user in the request.
        clientNonce,

        // but WordPress will not use this, either. Because we're sending a JSON payload.
        _wpnonce: clientNonce
      })
    });
    ...
  } catch (e) {
    ...
  }
};

Or you can also send the nonce as a query string (in the URL) like so:

`${apiBaseUrl}/pluginFolder/1.0/loadAll?_wpnonce=` + clientNonce

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745176085a4615198.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信