WordPress REST API – Allow anyone to POST

Solution:1

There are three different options to authenticate to the REST API:

  1. Cookie – this is what you are using now
  2. OAuth – requires the OAuth plugin and embedding key on the front end
  3. Basic – requires embedding the username/password on the front end

See the documentation on using these methods here: http://v2.wp-api.org/guide/authentication/.

There are obvious security risks when embedding the auth info on the front end, which is required by OAuth and Basic as anyone will be able to authenticate as the user the key is associated with. I’m not familiar enough with the WP OAuth plugin to know how granularly you can control access, but I don’t think you really can.

The easiest solution is to write your own method outside the REST API to handle these updates (or contribute to the project to make unauthenticated requests possible). I wrote up a guide for Creating AJAX Functions on my website, but basically you want to attach a function to the wp_ajax_nopriv_* hook, where the * is the “action” parameter of your request. In your hooked PHP function you handle the post insertion and respond with JSON (you could even match the WP REST API format).

PHP

// insert new post
function create_post_33741541() {
    // use the $_POST to create your post
    $args = array(
         'post_title' => isset( $_POST['title'] )? $_POST['title'] : 'Empty Title',
         // more parameters....
    );
    $post_id = wp_insert_post( $args );

    // make a response
    $response = array( 'post_id' => $post_id, 'message' => 'post created!' );

    // set the content type and return json encode response, then exit
    header( 'Content-type: application/json' );
    die( json_encode( $response ) );
}
// use wp_ajax_nopriv to access from front end
add_action( 'wp_ajax_nopriv_create_post_33741541', 'create_post_33741541' );
add_action( 'wp_ajax_create_post_33741541', 'create_post_33741541' );

JavaScript

function createThePost(){
    var data = {
        // use the part after "wp_ajax_nopriv" as the action
        action: 'create_post_33741541',
        title: 'Your title',
        // other params
    };

    $.ajax({
        method: "POST",
        url: ajaxurl,
        data: data,
        // your handlers
    });
}

Solution:2

About Basic Authentication

First of all, basic authentication won’t work until you install a special plugin, what plugin – depends on a way you choose. I will show you two of them.

Using username and password

This method isn’t recommended in WordPress Codex, because in each API call you have to send actual usernames and passwords, but you can use this method for test purposes.

To begin using it, you have to download a special plugin from github (I use the link from the official WordPress documentation page).

 

There is no way to perform Basic Auth in WordPress Rest API without this plugin installed. Once the plugin is activated on your website (I mean the website you want to interact with API), we can try examples below.

Using application passwords

Ok, this method is much better. You have to install Application Passwords plugin, it is available from WordPress plugins repository, so you can find it in your website admin area on the Plugins > Add New page.

 

Once you installed this plugin, make sure, that your REST API is not turned off, then go to the very bottom of a user profile page and generate an app password there.

 

No needs to use user’s actual passwords anymore.

Create a Post

Where to insert all the code from this post? I hope you know this but just in case.

First of all I want to remind you that we have 2 websites.

  • The first website – is the website where the post should be created, the first website also should have any of the mentioned above plugins installed.
  • The second website – is the website that will interact with the first one. It will have all the code.

You can see wp_remote_post() function in the code – it is a WordPress function, so you have to insert in somewhere inside WP environment. For my test purposes I just created a randomly named PHP file just in WordPress root directory and added at the beginning of the file require('wp-load.php');. When I try to access this file in browser, it does the work.

LOGIN:PASSWORD on line 3 is the pair of username and password of a website user (the first website, and if you’ve installed Application Passwords, you have to use the generated token instead), that have the capabilities to create, update and delete posts.


$api_response = wp_remote_post( 'https://WEBSITE/wp-json/wp/v2/posts', array(
 	'headers' => array(
		'Authorization' => 'Basic ' . base64_encode( 'LOGIN:PASSWORD' )
	),
	'body' => array(
    		'title'   => 'My test',
		'status'  => 'draft', // ok, we do not want to publish it immediately
		'content' => 'lalala',
		'categories' => 5, // category ID
		'tags' => '1,4,23' // string, comma separated
		'date' => '2015-05-05T10:00:00', // YYYY-MM-DDTHH:MM:SS
		'excerpt' => 'Read this awesome post',
		'password' => '12$45',
		'slug' => 'new-test-post' // part of the URL usually
		// more body params are here:
		// developer.wordpress.org/rest-api/reference/posts/#create-a-post
	)
) );

$body = json_decode( $api_response['body'] );

// you can always print_r to look what is inside
// print_r( $body ); // or print_r( $api_response );

if( wp_remote_retrieve_response_message( $api_response ) === 'Created' ) {
	echo 'The post ' . $body->title->rendered . ' has been created successfully';
}