2

I'm able to use the Rest API for calls that don't need auth, but I'm having an auth issue for the routes that require it. Here is part of a .php view template for an admin page:

<div id="nonceCreator">
  <script>
    let _wpnonce = <?php echo json_encode(wp_create_nonce('wp_rest')); ?>;

    let cookiesArray = <?php echo json_encode($_COOKIE) ?>;
  </script>
</div>

<div id="reactScriptInjection">
  <div id="adminRoot"></div>
  <script src="<?php echo PLUGIN_FOLDER_URL . "shared/" ?>adminArea.bundle.js"></script>
</div>

The cookies array and nonce seem to pass correctly:

wordpress_69cb7e12fdbb27dfb56056fb4f6b39c8: "<username and long key removed>"
wordpress_logged_in_69cb7e12fdbb27dfb56056fb4f6b39c8: "<username and long key removed>"
wordpress_test_cookie: "WP Cookie check"
wp-settings-1: "unfold=1&mfold=o"
wp-settings-time-1: "1562861991
"=====cookiesArray====="

bac3c6<digits removed> =====_wpnonce=====

The auth request sends back 401 unauthorized however:

Promise {<pending>}
__proto__: Promise
[[PromiseStatus]]: "resolved"
[[PromiseValue]]: Object code: "rest_not_logged_in"
data: {status: 401}
message: "You are not currently logged in."
__proto__: Object
"=====response.json()====="

and here is the api call

// from the relevant react.js component's source
const getUserNameFromRestApi = () => {
    console.log(_wpnonce, `=====_wpnonce=====`);

    fetch('http://localhost/wptest2/?rest_route=/wp/v2/users/me', {
      method : 'get',
      mode : 'cors',
      headers : {
        'Access-Control-Allow-Origin' : '*',
        'X-WP-Header' : _wpnonce
      }
    })
      .then(response => console.log(response.json(), `=====response.json()=====`))
      .catch(error => console.log(error, `=====error=====`));
  };

I don't think Access Control Origin plays a factor yet as I'm loading the output bundle.js within an admin page in wordpress.

However, I was able to get another plugin to do a successful authenticated fetch. Only difference was that plugin didn't use react.js, but rather vanilla javascript instead.

I thought cookies might be the problem but you see the $_COOKIE array output above. Also the nonce worked in that other plugin so I think I set it up correctly above too.

What else could it be then? I'm thinking something is wrong with the data flow.

  • I would strongly advise against putting cookies in a JS array for security reasons, JS can already access cookies directly – Tom J Nowell Jul 16 at 12:29
  • Good to know, I will look into it. FYI this was just for debugging and the plugin is not public facing yet – Sean Dezoysa Jul 16 at 12:37
  • Is that X-WP-Header just a typo in the question? Because it should be X-WP-Nonce .. – Sally CJ Jul 16 at 13:30
  • 1
    @SallyCJ that was indeed the issue, good catch and thanks – Sean Dezoysa Jul 16 at 13:45
  • 1
    @SallyCJ can you post that as a proper answer so I can upvote? – Tom J Nowell Jul 16 at 14:06
3

The problem is that you're not using the correct name for the REST API nonce header — the correct name is X-WP-Nonce, but you used X-WP-Header:

fetch('http://localhost/wptest2/?rest_route=/wp/v2/users/me', {
  method : 'get',
  mode : 'cors',
  headers : {
    'Access-Control-Allow-Origin' : '*',
    'X-WP-Header' : _wpnonce // here you used the wrong name
  }
})

Reference from the REST API Handbook:

For developers making manual Ajax requests, the nonce will need to be passed with each request. The API uses nonces with the action set to wp_rest. These can then be passed to the API via the _wpnonce data parameter (either POST data or in the query for GET requests), or via the X-WP-Nonce header.

So make sure to use the correct header name. :)

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.