Getting the WordPress Rest API running with Basic Auth and Application Passwords

August 15, 2016

At Ravenna we are in the earlier stages of testing how the WordPress REST API can augment our efforts both on and offsite. We are actively planning several implementations for onsite but are intrigued by offsite implementations that consume or update data.

For our offsite purposes and testing, we wanted a sandbox where we could play around, break things, and in general begin exploring possibilities.

Over the weekend we poked around with getting a sandbox running and ran into snags with authentication.

While you can consume via GET requests, POST requests require authentication by default.   In production we would, of course, use OAuth, but for testing, we want to get the authentication out of the way so that we can see what works.

The REST API docs are functional and and the Authentication portion notates the basics that are required.  Your basic options for off-site are Basic Authentication or OAuth.  Since we didn’t want to roll OAuth just yet we began working with Basic Auth.  This is where things get tougher based on a simple out of the box approach.

Our setup is as follows:

  • WP REST API Version 2.0-beta13.1
  • JSON Basic Authentication  Version 0.1
  • Default WordPress 4.5.3 with the 2016 theme running and no modifications
  • Basic shared hosting on Dreamhost (for testing)

The docs call for using HTTP Basic Auth and installing the Basic Auth Plugin.   However if you have tried this with the V2 version of the WP REST API,  and a POST request, it doesn’t work.  The request returns:

{
  "code": "rest_not_logged_in",
  "message": "You are not currently logged in.",
  "data": {
    "status": 401
  }
}

A quick Google of “WP rest api post with basic authentication errors” returns quite a few issues around this.  You can also look at the issues section of the Basic Auth plugin and find that its a known issue.

We also tried the Application Passwords plugin and had the same result.   Our testing at this point was 100% inside POSTMAN, which we love for testing these types of early implementations.

The solution we found was on this Github Issue.  Basically you have to append the .htaccess with a small bit to make sure Authorization headers and handled correctly.

RewriteRule ^index\.php$ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]

A quick review of our .htaccess had the first part: RewriteRule ^index\.php but not the rest.    Adding this rule paired with the Application Passwords plugin worked for our sandbox.

Our POST request in js looks like:

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}};

    $.ajax({
      url: baseURL + 'pages/' + id,
      type: 'POST',
      crossDomain: true,
            dataType: 'json',
   			data: OUR DATA,
            beforeSend: function ( xhr ) {
            xhr.setRequestHeader( 
            	'Authorization', 'Basic ' + Base64.encode( 'USER:APPLICATION PASSWORD' ); 
            );
        },
      success: function(data, txtStatus, xhr){
            console.log( data );
           console.log(txtStatus)
        	},
      error: function(data, txtStatus, xhr){
            console.log( data );
            console.log( xhr.status );
      }
    });

With this simple setup we are able to test the calls we want to make without spending time on authentication.  We know that our WP password is getting sent in each request and that presents a security issue.  We would never launch production code with this setup. We’ll eventually add in OAuth but for now for testing purposes, this setup works fine.

Having trouble getting the WP REST API up and running with Basic Auth, let us know.  We’d be happy to help.

 

  • Critter

    I have been pulling my bloody hair out with this issue. For some reason I can get oauth & basic working on my local server, but our dev/production servers. It’s been kicking my ass for days. Everyone of my google searches kept leading me back in a bloody circle :/ But adding that bit to the .htaccess files sorted it. Thanks for writing about your findings..

    • ravenna

      Glad that helped you. We’d love to hear more about what you are working on. We have begun playing with the REST API but its cool to hear what others are doing.


We do our best work face to face.

Send an email to tj@ravennainteractive.com or call us at 206.427.0000 and we will setup a time and place to meet.

 

 

Lets chat