I'm working on a front-end app which ties into wordpress API which sits on a seperate domain.
I'm wanting to retrieve a post draft so when the user clicks "Preview Post" in the wordpress admin panel, it opens my app with the correct content.
I'm loading some Javascript into the WP Admin so I can amend all "Preview Post" links in the admin panel with a wp_nonce token for authentication purposes. This is done using the below snippet, which tweaks the preview post link into for example: http://example.com/blog?p=127&preview=true&auth=16045802ee
function admin_inline_js(){
// Grab URL
echo '
<script>
document.addEventListener("DOMContentLoaded", function() {
// Grab all preview anchors
var anchors = document.querySelectorAll("a[href*=\'preview=true\']"), i;
// Loop through and amend to remove the trailing slash, as WP doesnt provide any easy method to achieve this.
for(i = 0; i < anchors.length; i++) {
anchors[i].href = anchors[i].href.replace("blog/", "blog") + \'&auth=' . wp_create_nonce('wp_rest') .'\';
}
});
</script>
';
}
add_action( 'admin_print_scripts', 'admin_inline_js' );
At http://example.com/blog?p=127&preview=true&auth=16045802ee
, the auth
parameter is then used to post a request back to wordpress to retrieve the draft with an ID of 127, with a nonce token of 16045802ee
. However this isn't working, and I'm getting this response:
object(stdClass)#459 (3) { ["code"]=> string(25) "rest_cookie_invalid_nonce" ["message"]=> string(23) "Cookie nonce is invalid" ["data"]=> object(stdClass)#532 (1) { ["status"]=> int(403) } }
Can anybody spot what I'm doing wrong here? :/
Thanks.
There are two issues you are facing:
A Wordpress "nonce" is a tool that is only intended to protect against CSRF tokens. Really useful when writing plugins for the admin panel, but not useful for authenticating against the API.
Passing authentication details over the API is blocked by the default-prescribed .htaccess file.
You need to pass authentication details over the API in order to receive the responses containing the protected data. For simplicity, I recommend using HTTP Basic Auth to get it working first, optionally enhancing your code with more secure authentication methods such as OAuth in the future.
I recommend creating a new user specifically for API usage, rather than passing admin details around in text files on your server.
Once you have your user created, you can request the draft post using simple cURL in PHP as follows:
This will set request header containing the username and password, and as long as nothing interferes with this header before it gets to Wordpress, you will receive your post details in
$postObject
and you can stop reading here. You're done.However, for a bit of extra fun, the Wordpress-prescribed default
.htaccess
file drops HTTP headers, so if you're using that you'll need to fix it yourself. Basically, the Wordpress scripts need to seePHP_AUTH_USER
andPHP_AUTH_PW
keys within the$_SERVER
variable for this to work.A quick fix is to include the following rule as the first RewriteRule in .htaccess:
which will split the headers into variables prefixed with "REMOTE_USER", and the following PHP can be used to populate the expected fields back again (perhaps this can go in
index.php
).