Using OAuth 1.0 with the WordPress API & Custom Endpoints

This very long article covers setting up OAuth 1.0 to work with the core version of the WordPress API.

We will be generating client keys, oauth tokens, a custom endpoint and allowing access to our API only from those whom we have manually authenticated via OAuth.

Before we begin, I have 2 local installs of WordPress:

http://wp-api-main/

This is our main API website that our client will make requests to.

http://wp-api-client/

This is our client website that will make requests to the API website.

I have listed quite a few resources that I used to put together this tutorial at the bottom of the article. In some cases, I’ve just copied the code or steps. If you get stuck or want more info, I highly encourage you to read those resources. They will definitely be worth your time!

Get some coffee and let’s begin!

Test to make sure you can connect to the API.

Add the following code to your plugin on your client site.

Change the $url value to match the URL of the API site’s URL. So it will be something like http://example.com/wp-json

Mine is installed on my local machine that’s why the URL is http://wp-api-main/wp-json

Then create a new page and add this shortcode to the page [test_api_connection]

Open the page and you should see content like this:

Array
(
    [name] => WP-API Main
    [description] => Just another WordPress site
    [url] => http://wp-api-main
    [home] => http://wp-api-main
    [namespaces] => Array
        (
            [0] => oembed/1.0
            [1] => wp/v2
        )

    [authentication] => Array
        (
        )

    [routes] => Array
        (
            [/] => Array
                (
                    [namespace] => 
                    [methods] => Array
                        (
                            [0] => GET
                        )

                    [endpoints] => Array
                        (
                            [0] => Array
                                (
                                    [methods] => Array
                                        (
                                            [0] => GET
                                        )
// ...

Here’s what mine looks like:

The thing to notice is that the [authentication] is an empty array. Let’s change that part.

Now go to your main API site and install and activate the “WordPress REST API – OAuth 1.0a Server” plugin.

Once installed and activated, go to Users > Applications and click the [Add New] button.

On the “Add Application” page you will fill in some values. “Consumer Name” and “Description” can be whatever you wish. Just put something that makes sense.

I’m not sure what the Callback does at this time so I just inserted something like “http://wp-api-main/auth/success”.

After you have filled in all 3 fields, click the [Add Consumer] button.

Now you will see that the Client has a Client Key and Client Secret under the “OAuth Credentials” section.

Copy those for later.

Client Key (consumer_key):

CUQVVujOraZd

Client Secret (consumer_secret):

dcsgQT9B99f2bMSj2IWwMpbmr9dZFE0wzLCK4sZue60jZ9v9

Now if you go back to the new page you created on your Client site which has the shortcode, the [authentication] array should have some values in it.

Now we need to hook up these keys with our client so that our client can then make subsequent authenticated API requests to our API site.

The details behind this process are complicated and covered in detail in some of the resource links I share at the bottom of this article especially on nobil.cc.

The method I found the easiest to use the above keys is with an app like Postman or Paw. Postman is free and also has a Chrome extension if you aren’t on a Mac. I’ll use Postman in this tutorial because it’s free.

For these next steps, I relied heavily on nobil.cc. It contains more background on this process. Definitely worth the read!

If you have questions about these next few steps, check that article, too.

Open the Postman app.

In the “Get” request URL field enter the URL of the main API website’s /oauth1/request path. I have entered

http://wp-api-main/oauth1/request

Under Authorization Type, choose OAuth 1.0

Enter the Consumer Key (ie. the Client Key) and Consumer Secret (ie. the Client Secret).

Click the [Update Request] button. This will automatically fill in the timestamp field and the Nonce field.

Your request URL will have been update to something like this:

http://wp-api-main/oauth1/request?oauth_consumer_key=CUQVVujOraZd&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1481140823&oauth_nonce=vRxe3poywrw&oauth_version=1.0&oauth_signature=csft+J7hOAR97WhE6nZoRFhUfZs=

Then click the [Send] button.

Scroll down to see the response. You should see something like this:

oauth_token=OXjySsfBdsbWa04BMFAJy6ox&oauth_token_secret=8O20H7lyZ2s0vaGwnF4QrkdNt26iFXbpRsoigMFiwylwgqLz&oauth_callback_confirmed=true

Save that string somewhere. We will need these 2 initial OAuth tokens:

oauth_token

OXjySsfBdsbWa04BMFAJy6ox

oauth_token_secret

8O20H7lyZ2s0vaGwnF4QrkdNt26iFXbpRsoigMFiwylwgqLz

Next, we will use the “oauth_token” value we just got and construct a URL like this (on our Main API site):

http://wp-api-main/oauth1/authorize?oauth_token=OXjySsfBdsbWa04BMFAJy6ox

Load the URL in your browser.

You will get a login-type screen which has a message like “Howdy eric,
“Client API Connection” would like to connect to WP-API Main.”

Click the [Authorize] button.

The next screen will have a message like this: “Your verification token is PvHs1j8ol5FqVd4QPv0eGt9t

verification token

PvHs1j8ol5FqVd4QPv0eGt9t

Copy that token down… we’ll need that later, too!

The last step is to get our access token.

So in Postman, enter this URL into the request URL field:

http://wp-api-main/oauth1/access

This time you will need to fill in your:

  • Consumer Key
  • Consumer Secret
  • Token
  • Token Secret

Clicking the [Update Request] button will fill in the nonce and timestamp and your request URL will be transformed into something like this:

http://wp-api-main/oauth1/access?oauth_consumer_key=CUQVVujOraZd&oauth_token=OXjySsfBdsbWa04BMFAJy6ox&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1481141563&oauth_nonce=dJemNhotMRa&oauth_version=1.0&oauth_signature=08eCfNrGqovw4OF6P2uNrymLSdE=

Next click the [Params] button to the right of the request URL.

Add 1 new row to the params. Set the key to “oauth_verifier” and the value to “PvHs1j8ol5FqVd4QPv0eGt9t” (which is the value we got in the previous step.

Then click the [Send] button. Note that you may need to click the [Update Request] again and then click [Send].

After you scroll down you will see your new tokens.

oauth_token=LLnMXOF4aYlktf4X6DhAy0fr&oauth_token_secret=Ig5jaC1GmavfWrvUgN7w16LJT5yZT03DHRddmqpKM71us8Rn

oauth_token

LLnMXOF4aYlktf4X6DhAy0fr

oauth_token_secret

Ig5jaC1GmavfWrvUgN7w16LJT5yZT03DHRddmqpKM71us8Rn

You can now disregard your old oauth_token and oauth_token_secret tokens. You won’t need the old ones anymore. You only need these new ones. Additionally, you can disregard your oauth_verifier code as well. You shouldn’t need that code any more.

OK, we are done with Postman and we now have the necessary OAuth tokens we need in order to make an authenticated API request.

The only thing is, our main API site does not require authentication yet. So let’s force it to require authentication.

On your main API site, install the Disable Rest API plugin.

So now we have 2 plugins installed on our main API site:

  • WP REST API – OAuth 1.0a Server
  • Disable REST API

Let’s make sure our API now requires authentication. Go to the test page you created on your client site and load the page again.

You should now see a 401 “rest_cannot_access” message like this.

Excellent! I bet you’ve never been so happy to see a 401 message. 🙂

So, now that we have the keys to get around that restriction and authenticate, let’s do so.

But we’re not out of the woods yet… unfortunately, not even close.

The next bit of code mostly comes from this Sitepoint article. Please refer to that for more details. In our case, we will make a class that handles sending the proper headers to an API that requires authentication. Time to get more coffee… I’ll be here when you get back.

We are going to create a new shortcode so that we can add it to our page with the other shortcode.

Let’s first go to our page and modify our page so it looks like this:

<h2>test_api_connection</h2>
[test_api_connection]

<h2>test_api_oauth_connection</h2>
[test_api_oauth_connection]

Then we need to add a new shortcode to our plugin so we can start testing our OAuth connection.

Here’s our new shortcode:

A few things to take note of…

We added a $method variable and set it to ‘GET‘. That matches our wp_remote_get() call.

We added the various keys that we created to a $keys array.

Then we passed the $keys, $url and $method variables as parameters to our new OAuth_Authorization_Header() class. More on that in a second.

We get the $header value from the get_header() method and then added our authorization header array to a new $args array.

Lastly, we modified our call to wp_remote_get() by adding the $args array as the second parameter to the function.

The rest of the shortcode code is the same as our first one.

OK, so what about the new OAuth_Authorization_Header class?

Well, it’s a modified and simplified version of the class in the Sitepoint article which is itself a modified and simplified version of the code from a Twitter WordPress HTTP client. Love me some open source!

Here’s the basic OAuth_Authorization_Header class without documentation or checks to ensure all the required data is present… it’s a starting point. Be sure to validate the incoming arguments.

So now when you load the page with your shortcodes on your client site, you should have one ‘access denied’ message and one with a successful response.

The last thing I want to do is set up a custom endpoint on my API site and make that custom endpoint protected. Currently, all of our endpoints are private because we installed the Disable REST API plugin. But what if you just want a single custom endpoint to be private, not all endpoints?

Here’s how we can do that.

First, disable the Disable REST API plugin on your main API site.

After you do that, now both your shortcodes on your client site should load a successful response like this:

Next, create a custom plugin on your main API site and add the following code to your plugin:

Basically, this creates a new endpoint and returns an array if successfully called.

Let’s tweak our URLs in our client plugin:

In the client plugins we have this:

$url = 'http://wp-api-main/wp-json';

Let’s change that to this to make a request to a specific endpoint:

$url = 'http://wp-api-main/wp-json/myapiplugin/v2/greeting';

Be sure to change the $url variable in BOTH shortcodes.

Then refresh the page on your client site with the shortcodes. You should now see 2 successful responses.

Perfect! Now, let’s make that new endpoint private so only authenticated clients can access it.

Change the Main API plugin to this:

You see we have added a new item to array in the third parameter of the call to register_rest_route(). We have added:

'permission_callback' => 'myapiplugin_permission_callback',

Then we added a new function to our plugin that returns ‘true‘ if the current user can update core WordPress or false if the user can not. Who is this user that “current_user_can” is referring to? That user is our client who we have granted permissions to through the OAuth key exchange (back in the Postman section of this article).

So now that we have added this new authentication code to our plugin, let’s go back to our client shortcode page and reload that page.

Now you should see 1 access denied message and one success message.

And now you have successfully set up OAuth1 with your WordPress API so that a client that you have explicitly granted access to can call a private endpoint that you have set up.

Resources

Here are some of the articles I referenced when putting my article together. They were a huge help so if you are looking for more information about some of these steps, do check these out: