Following the Wordpress documentation about the Rest Api, i can manage to make an ajax POST working, but only when logged in to Wordpress. Here are the basic files shown in the documentation:


wp_localize_script( 'wp-api', 'wpApiSettings', array(
    'root' => esc_url_raw( rest_url() ),
    'nonce' => wp_create_nonce( 'wp_rest' )
) );


$.ajax( {
    url: wpApiSettings.root + 'wp/v2/posts/1',
    method: 'POST',
    beforeSend: function ( xhr ) {
        xhr.setRequestHeader( 'X-WP-Nonce', wpApiSettings.nonce );
        'title' : 'Hello Moon'
} ).done( function ( response ) {
    console.log( response );
} );

I'm showing this example as it is presented as an easy one, but is not working when not logged in. It is always giving me a 401 Unauthorized response / “rest_cannot_create”...

Any tip ?

Thank you !


As stated in the documentation page you linked,

It is important to keep in mind that this authentication method relies on WordPress cookies. As a result this method is only applicable when the REST API is used inside of WordPress and the current user is logged in. In addition, the current user must have the appropriate capability to perform the action being performed.

Your JavaScript function is attempting to update a post - an interaction which affects the site's database. Thus the REST API requires authentication in order to perform the operation. While REST authentication behaviors can be modified using the rest_authentication_errors filter, it's highly inadvisable to disable authentication for the requests which require them by default, as doing so exposes your site to modification at virtually anyone's whim.

You may wish to investigate alternate means of authentication, as alluded to in the documentation page you linked.

| improve this answer | |
  • Thanx for the reply. I have tried them all for months now (OAuth, JWT, ...) ... there is always something going wrong. Feeling like I'm dumb. While i was trying to 'shadow login' as a hack to make POST work, yesterday a WP moderator wrote : "to post specific content does not necessarily require the user be logged in. A custom handler for requests sent to admin-ajax.php or admin-post.php can insert new posts or whatever without the user being logged in". So i went back to try stuff, still without success... May i ask what is your favorite way of authentication ? Cheerz... – jDelforge Mar 24 '17 at 1:59
  • I actually haven't written anything using the REST API which requires authentication - just front-ends displaying content. I'm rather fond of OAuth (though I'm not a big fan of setting it up!). What are you working on that you should want to be able to add/update posts without being logged in? The WP mod makes a good point - if you write your own AJAX handlers, you can decide whether or not a user must be logged in to do something simply by whether or not you include a is_user_logged_in() (or similar) check. – bosco Mar 24 '17 at 2:07
  • I need any visitor to be able to post ads from the front end (as draft). It is working perfectly when I'm logged in. Having so many difficulties to authenticate, i did try a 'shadow login' for any visitor, but then i had other problems with getting a wrong nonce on first load This is getting me nuts :) – jDelforge Mar 24 '17 at 2:15
  • 1
    Ah alright - I see what you're getting at. I think I have a two-part solution for you which comprises the "most WordPress-y" way to accomplish this - and we get to ignore authentication woes all together to boot. You'll need to register a custom post type to represent ads, and create a REST endpoint controller class which will determine how the new custom post type is available through the REST API. This will let you specify custom CREATE permissions allowing visitors to create ads while not exposing other content to visitor whims. – bosco Mar 24 '17 at 3:22
  • 1
    I can pull together a more complete answer tomorrow, - maybe throw it in a new "Visitor Posting via the REST API" question for posterity – bosco Mar 24 '17 at 3:34

Not the safest way, but this plugin is still working today :

Basic Authentication handler

Once installed, using Javascript, we'll just use the Base64 variable :

var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f<e.length){n=e.charCodeAt(f++);r=e.charCodeAt(f++);i=e.charCodeAt(f++);s=n>>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(f<e.length){s=this._keyStr.indexOf(e.charAt(f++));o=this._keyStr.indexOf(e.charAt(f++));u=this._keyStr.indexOf(e.charAt(f++));a=this._keyStr.indexOf(e.charAt(f++));n=s<<2|o>>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(/\r\n/g,"\n");var t="";for(var n=0;n<e.length;n++){var r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r)}else if(r>127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n<e.length){r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r);n++}else if(r>191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}};

... and add in the beforeSend function :

xhr.setRequestHeader( 'Authorization', 'Basic ' + Base64.encode( 'YOUR_USER_NAME' + ':' + 'YOUR_PASSWORD' ); );

Bingo !

| improve this answer | |

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.