OAuth in WP REST API. How and why.

In this post, I try to describe what OAuth authentication is, how to do it, and why it is needed.

This is a translation of a post of mine originally written in Japanese, and based on and following the flow described in a documentation written by @rmccue, the author WP REST API – OAuth 1.0a Server plugin, and the API.

When you find something wrong, I’m happy to get feedbacks as comments or reply to @shinichiN on twitter.

Step 0. Getting Client Key and Client Secret from WordPress

We are using WP-API/OAuth1 · GitHub plugin to turn our WordPress into a OAuth provider. (And if your WordPress is 4.4.n, the WP REST API plugin needs to be activated, too.) This plugin offers a GUI to create client key and client secret under Users menu in admin panel.

GUI of OAuth server plugin
GUI of OAuth server plugin

Name and Description is for human readability so you can put any name you want. In this post we don’t utilize the callback url so input http://example.com/auth/success or such.

You will see Client Key and  Client Secret which we use in the authentication flow.

These credentials can be generated with wp-cli commands, too: $ wp oath1 add.

Summary of OAuth flow and why this is useful

OAuth1/Auth-Flow.md at master · WP-API/OAuth1 says:

The key to understanding how OAuth works is understanding the authorization flow. This is the process clients go through to link to a site.

And the flow is:

1. Temporary Credentials Acquisition

The client gets a set of temporary credentials from the server.

To get these credentials, we use the client key / secret we just got from the WordPress admin panel. These temporary credentials are called Request Token.

2. Authorization

The user “authorizes” the request token to access their account.

This is when a logged in human user will authorize an application to work on behalf of them.

3. Token Exchange

The client exchanges the short-lived temporary credentials for a long-lived token.

In other words, client application exchanges their Request Token for a Access Token. Access token is the token which the client application will use to get protected data, creating, updating deleting data in WordPress through the WP REST API.

Why OAuth ?

Assuming that there is a WordPress site which is WP REST API activated, and what we want to do is to perform something only logged-in users can,  with third-party applications.

We want to get post meta data which is not public to non-authorized request. We want to add posts, update taxonomy terms, delete users from iPhone apps, desktop apps and web apps, through WP REST API.

The first idea we come up with might be “Let’s send our login name / password and let the WordPress know that the client application is me!” but this is really bad in several ways.

  • Sending user name and password through network is bad.
  • Giving your ID and password is bad, especially the app is a third-party owned by someone else.

To avoid these problems is the reason we need OAuth. Through the 3 steps flow of authentication, the communication is happening among a WordPress site, a third-party application, and a logged in user. In step 2, a human user will be logged in to the website, in this case our WordPress,  and authorize the third party app. After the authorization, application will be able to perform what the user allows.

To enable this, giving an app the right to do things without giving the password, is the purpose of OAuth.

Three endpoint URLs to communicate

We now know that there will be 3 steps in our process and there are 3 endpoint urls that correspond to each steps.

These 3 endpoints are offered by the WP OAuth plugin and are shown when we access /wp-json on your WordPress.

3 endpoints show in /wp-json response
3 endpoints shown in /wp-json response json
  1. $.authentication.oauth1.request : the endpoint to retrieve a request token and secret.
  2. $.authentication.oauth1.authorize : the endpoint a user will authorize the app.
  3. $.authentication.oauth1.access : the endpoint where the app will get the access token.

In the 3 steps, we are going to send 3 requests to these endpoints.

Step 1: Temporary Credentials Acquisition

The first step is acquiring the temporary credentials, which is also called request token and the endpoint url is http://example.com/oauth1/request.

Toward this endpoint, we send a signature created of a few things, including the client key / secret we got from the WordPress admin UI.

The image below is how I input my key and secret into the Paw UI.

asefa
Input the client key and secret in the fields called Consumer Key and Consumer Secret in Paw’s UI. On the right, you can see the response from WordPress showing the oauth_token and oath_token_secret in return.

Paw shows us what the actual request sent to the server was and it was like this.

GET /oauth1/request HTTP/1.1
Authorization: OAuth oauth_consumer_key="fbQ9KPUmdDLP", oauth_nonce="4Lxk40ujU5KQU7j53E06dKGlLwQkKm1W", oauth_signature="Ra%2BrRiy2tLKk9ub0qMABW4g57gQ%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1451907555", oauth_version="1.0"
Host: wp-api.dev
Connection: close
User-Agent: Paw/2.2.7 (Macintosh; OS X/10.9.5) GCDHTTPRequest

At the line 2, we can see the Authorization header which includes several key=value strings, separated by commas and spaces. Let’s see what they are.

  • oauth_consumer_key is the Client Key we got from WordPress.
  • oauth_nonce is a random string created automatically by Paw. nonce stands for  number used once and is used to prevent the OAuth provider performing a procedure more than once if the same request is sent.
  • oauth_timestamp is also generated by Paw. This is used by the server to control how long it needs to hold the nonce and tokens. What’s the point of a timestamp in OAuth if a Nonce can only be used one time? – Stack Overflow might be good if interested.
  • oauth_signature is also generated by Paw and this is the main part of this request. How Paw generates it ( and how we should do it with our program when creating an app ) can be described as below. For further reading, please go to the github repository of the plugin, OAuth1/Signing.md.
    • combine client key, timestamp, nonce into a string in a predefined manner.
    • create another string with client key and client secret.
    • Hash the 2 strings with HMAC-SHA1 method.

Note that the client secret it self is not sent to the server. It is only used in the generating process of  the hashed oauth_signature. Once the request is sent, our WordPress site will check them by doing the same thing as the client has done. WordPress knows the client secret, because WP is the provider of it, and so can tell if the request is sent by a valid app.

When the check is done, WordPress will respond sending back oauth_token and oauth_token_secret and these are the temporary credentials, the request tokens.

Here is the response.

HTTP/1.1 200 OK
Date: Mon, 04 Jan 2016 10:00:56 GMT
Server: Apache
X-Powered-By: PHP/7.0.0
Content-Length: 134
Connection: close
Content-Type: application/x-www-form-urlencoded; charset=utf-8

oauth_token=CZpmXOtP98rsvrBk668QZZxE&oauth_token_secret=CTAdf4c1ZdLzoJJvC195VoMN3t9t3oPphK3sAbSceHYfUjwl&oauth_callback_confirmed=true

Step 2: Authorize

Now we are going to use the oauth_token with the second endpoint url, /oauth1/authorize/. In this step, a human logging-in is required and WordPress does several redirections so we use a browser. Access http://example.com/oauth1/authorize?oauth_token=<the oauth_token we got in the step 1> with your browser.

Accessed, you will be redirected to the authorization screen, or the WordPress login form if not yet logged in.

The authorization screen.
The authorization screen.

Here, a human user will give the authority, capability to access and change the data inside WordPress. Note that the oauth_token parameter is known only to the user who’s passed the step 1, where can be passed only by the one with the client key /secret.

If we click the “Authorize” link, WordPress will mark the token as valid and will return us a oauth_verifier, a string to prevent CSRF. We use it in the next step.

The screen we see after authorization. Should be redirected to oauth callback url if defined well.
The screen we see after authorization. Should be redirected to oauth callback url if defined well.

Step 3: Token Exchange

In this final step, we are getting the access token. The endpoint url is /oauth1/access/ and we are going to send a POST request with another signature and verification token we got in the step 2.

WordPress will check the signature and if confirmed, will give us a new pair of oauth_token and oauth_token_secret, which we call access token. After exchanging the tokens, we can discard the old oauth_token, oauth_token_secret and oauth_verifier because we don’t need them anymore.

Building a request in Paw is a bit tricky. We need to add oauth_verifier="<oauth_verifier we got in the step 2>" in the Additional Params field.

Add oauth_verifier and request /oauth1/access/ and get the new tokens.
Add oauth_verifier and request /oauth1/access/ and get the new tokens.

The request looked like this.

POST /oauth1/access/ HTTP/1.1
Authorization: OAuth oauth_consumer_key="fbQ9KPUmdDLP", oauth_nonce="cEsC2kNG16ETXhjmjCb4wOe0otwH6fhN", oauth_signature="KgLDxSAYSbkGh1htQwPPZ8PMoKw%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1451915663", oauth_token="CZpmXOtP98rsvrBk668QZZxE", oauth_version="1.0", oauth_verifier="Etrc3Asa5EYRikFxUN6WMzJT"
Host: wp-api.dev
Connection: close
User-Agent: Paw/2.2.7 (Macintosh; OS X/10.9.5) GCDHTTPRequest
Content-Length: 0

This time again Paw’s generated a signature using

  • client key / secret
  • oauth_token / secret ( the old request token )
  • nonce, verifier, timestamp
  • the HMAC-SHA1 method

The secrets are not sent. It’s impossible to get the same signature without knowing the secret and so WordPress can know that the client has the secrets, and so is safe and authorized.

When the check is done, WordPress will give us the access tokens. They have the same key names, oauth_token and oauth_token_secret. We just delete the request tokens away and switch them with the new ones.

Now, the application is authorized and linked to the website.

Send request to the WP REST API with OAuth access token

Let’s send to the API a request, which is allowed only to authenticated apps. Here we try getting post meta data.

Switch the oauth_token and oauth_token_secret in the Paw to new ones and GET request to /wp-json/wp/v2/posts/<post_id>/meta.

Requesting post meta data and getting the json
Requesting post meta data and getting the json

The request looks like this and we can see that the signature created with the same method is sent.

GET /wp-json/wp/v2/posts/1/meta HTTP/1.1
Authorization: OAuth oauth_consumer_key="fbQ9KPUmdDLP", oauth_nonce="UqeSQCG8m1C4Px5QMcH2Je5OhEc6OQr7", oauth_signature="ZfwTyXEm3UE6CQJ5E52D82QNU%2B0%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1451916352", oauth_token="PdJ2r3GHkbKlwQNKb5OZoZRE", oauth_version="1.0"
Host: wp-api.dev
Connection: close
User-Agent: Paw/2.2.7 (Macintosh; OS X/10.9.5) GCDHTTPRequest

That’s all!

Happy WP-REST-APIing!

One thought on “OAuth in WP REST API. How and why.

Comments are closed.