最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

json - Can't GET draft posts via REST API from headless frontend

programmeradmin2浏览0评论

I have a headless install of Wordpress on v5.4.0. The frontend can't GET any post that is in draft status, though when accessing the API url directly the data is returned without an issue. I'm assuming this is cookie/auth related. Note, I'm dynamically grabbing the nonce values from the backend, showing full strings here for the sake of argument. Here's my setup and screenshots of the responses:

Request URL: /wp-json/wp/v2/pages/19060?wpnonce=23c01b3b12&_embed=true

Called on the frontend using isomorphic-unfetch (also tried with axios) like so:

fetch("/wp-json/wp/v2/pages/19060?wpnonce=23c01b3b12&_embed=true", {
  credentials: "include"
})

Here's the request/response from the frontend, which is not working (this does work for all published content):

With this body:

{
  "code":"rest_forbidden",
  "message":"Sorry, you are not allowed to do that.",
  "data":{
  "status":401
  }
}

When trying to access the data directly, I see two different responses depending on the wpnonce query parameter underscore:

This works (using _wpnonce) returning the proper JSON data:

/wp-json/wp/v2/pages/19060?_wpnonce=23c01b3b12&_embed=true

Details:

This does not (using wpnonce):

/wp-json/wp/v2/pages/19060?wpnonce=23c01b3b12&_embed=true

Details:

Returns the same response error that the frontend does:

{
  "code":"rest_forbidden",
  "message":"Sorry, you are not allowed to do that.",
  "data":{
  "status":401
  }
}

EDIT:

I've also tried the X-WP-Nonce header mentioned here (/) and it doesn't seem to be recognized:

fetch(postUrl, {
  credentials: "include",
  headers: {
    "X-WP-Nonce": wpnonce
  }
})

{"code":"rest_cookie_invalid_nonce","message":"Cookie nonce is invalid","data":{"status":403}}

EDIT 2:

On a clean install of WP and a new barebones frontend (html + jquery) I'm seeing the same issue. However, I find that the nonce is valid when generating the preview link, but invalid when WP tries to verify using rest_cookie_check_errors. How can the same nonce with the same action (wp_rest) fail verification?:

I'm seeing that wp_get_session_token() is failing because there's no cookie found on REST requests. (.4/src/wp-includes/pluggable.php#L2140) Isn't the point of the nonce to not require cookies? Could it be an issue with cross-domain cookie paths?

I am sending credentials in the XHR. Here's my frontend test code:

// GET page with Nonce header
$.ajax({
  url: postUrl,
  method: "GET",
  xhrFields: {
    withCredentials: true
  },
  beforeSend: function(xhr) {
    xhr.setRequestHeader("X-WP-Nonce", wpnonce);
    xhr.setRequestHeader("Content-Type", "application/json");
  }
})

Two questions:

  1. Mainly, how can I get draft post data using nonce values from the frontend?
  2. Why in the world would the _wpnonce / wpnonce query vars show different results on the frontend and backend?

I have a headless install of Wordpress on v5.4.0. The frontend can't GET any post that is in draft status, though when accessing the API url directly the data is returned without an issue. I'm assuming this is cookie/auth related. Note, I'm dynamically grabbing the nonce values from the backend, showing full strings here for the sake of argument. Here's my setup and screenshots of the responses:

Request URL: http://wordpress.test/wp-json/wp/v2/pages/19060?wpnonce=23c01b3b12&_embed=true

Called on the frontend using isomorphic-unfetch (also tried with axios) like so:

fetch("http://wordpress.test/wp-json/wp/v2/pages/19060?wpnonce=23c01b3b12&_embed=true", {
  credentials: "include"
})

Here's the request/response from the frontend, which is not working (this does work for all published content):

With this body:

{
  "code":"rest_forbidden",
  "message":"Sorry, you are not allowed to do that.",
  "data":{
  "status":401
  }
}

When trying to access the data directly, I see two different responses depending on the wpnonce query parameter underscore:

This works (using _wpnonce) returning the proper JSON data:

http://wordpress.test/wp-json/wp/v2/pages/19060?_wpnonce=23c01b3b12&_embed=true

Details:

This does not (using wpnonce):

http://wordpress.test/wp-json/wp/v2/pages/19060?wpnonce=23c01b3b12&_embed=true

Details:

Returns the same response error that the frontend does:

{
  "code":"rest_forbidden",
  "message":"Sorry, you are not allowed to do that.",
  "data":{
  "status":401
  }
}

EDIT:

I've also tried the X-WP-Nonce header mentioned here (https://developer.wordpress/rest-api/using-the-rest-api/authentication/) and it doesn't seem to be recognized:

fetch(postUrl, {
  credentials: "include",
  headers: {
    "X-WP-Nonce": wpnonce
  }
})

{"code":"rest_cookie_invalid_nonce","message":"Cookie nonce is invalid","data":{"status":403}}

EDIT 2:

On a clean install of WP and a new barebones frontend (html + jquery) I'm seeing the same issue. However, I find that the nonce is valid when generating the preview link, but invalid when WP tries to verify using rest_cookie_check_errors. How can the same nonce with the same action (wp_rest) fail verification?:

I'm seeing that wp_get_session_token() is failing because there's no cookie found on REST requests. (https://core.trac.wordpress/browser/tags/5.4/src/wp-includes/pluggable.php#L2140) Isn't the point of the nonce to not require cookies? Could it be an issue with cross-domain cookie paths?

I am sending credentials in the XHR. Here's my frontend test code:

// GET page with Nonce header
$.ajax({
  url: postUrl,
  method: "GET",
  xhrFields: {
    withCredentials: true
  },
  beforeSend: function(xhr) {
    xhr.setRequestHeader("X-WP-Nonce", wpnonce);
    xhr.setRequestHeader("Content-Type", "application/json");
  }
})

Two questions:

  1. Mainly, how can I get draft post data using nonce values from the frontend?
  2. Why in the world would the _wpnonce / wpnonce query vars show different results on the frontend and backend?
Share Improve this question edited Apr 2, 2020 at 15:14 theLucre asked Apr 1, 2020 at 23:52 theLucretheLucre 311 silver badge5 bronze badges 11
  • 1 Please review the documentation for authentication with the REST API: developer.wordpress/rest-api/using-the-rest-api/… Both your questions are answered. – Jacob Peattie Commented Apr 2, 2020 at 0:17
  • Edited to note the X-WP-Nonce header in the get request. Am I missing something else? – theLucre Commented Apr 2, 2020 at 0:45
  • It sounds like your nonce is recognised, but is invalid, are you sure it's generated correctly? – Tom J Nowell Commented Apr 2, 2020 at 0:48
  • 1 @theLucre, if you originally mentioned 'from external domain' in the question, I would've just suggested you to use an authentication plugin (just like JWT) because from remote apps, that's what the WordPress core suggests. After all, I don't think it's a good idea to include the cookies in the request (the credentials: 'include' in fetch()). – Sally CJ Commented Apr 2, 2020 at 22:57
  • 1 Thanks @SallyCJ. I assumed headless WP meant two domains. Apologize for any confusion and I appreciate your help! – theLucre Commented Apr 3, 2020 at 3:08
 |  Show 6 more comments

1 Answer 1

Reset to default 1

Ok, so technically I didn't solve the issue that prevented me from accessing posts in draft status from an external domain where the frontend is hosted using only nonce values. My guess is that the logged_in cookie was not set/could not be read on the frontend side to verify the nonce value during an external AJAX request.

That being said, I installed the JWT Authentication for the WP REST API plugin (https://github/Tmeister/wp-api-jwt-auth) and now require admins to login once on the frontend preview page to set the token in local storage.

发布评论

评论列表(0)

  1. 暂无评论