14

This is not really a question but a guide on how to make authenticated requests to the Wordpress API using JWT. I'm writing this as a reminder to myself and for those who may need some help with the same topic.

  • 3
    You should format this as a question, then post the solution as an actual answer. Otherwise it looks like an unanswered question. – Jacob Peattie Apr 2 '18 at 7:26
  • 1
    There is also this fine guide firxworx.com/blog/wordpress/… – Armando Feb 15 at 18:16
16

Why JWT authentication

I'm building a site that uses Wordpress as the back-end, and a React+Redux app as the front-end, so I'm pulling all the content in the front-end by making requests to the Wordpress API. Some requests (mainly, POST requests) must be authenticated, which is when I came across JWT.

What we need

To use JWT authentication with Wordpress, we first need to install the JWT Authentication for WP REST API plugin. As is explained in the plugin's instructions, we also need to modify some core Wordpress files. In particular:

In the .htaccess file included in the Wordpress installation's root folder, we need to add the following lines:

RewriteEngine on
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule ^(.*) - [E=HTTP_AUTHORIZATION:%1]

In the wp-config.php file, also included in the Wordpress installation's root folder, we need to add these lines:

define('JWT_AUTH_SECRET_KEY', 'your-top-secret-key'); // Replace 'your-top-secret-key' with an actual secret key.
define('JWT_AUTH_CORS_ENABLE', true);

Testing to see if JWT is available

To verify that we can now use JWT, fire up Postman and make a request to the Wordpress API's default 'index':

http://example.com/wp-json/

A few new endpoints, like /jwt-auth/v1 and /jwt-auth/v1/token should have been added to the API. If you can find them in the response to the above request, it means JWT is now available.

Getting the JWT token

Let's stay in Postman for the moment, and let's request a token to the Wordpress API:

http://example.com/wp-json/jwt-auth/v1/token

The response will contain the JWT token, which is an encrypted key that looks something like this:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9sb2NhbGhvc3Q6ODg4OFwvZm90b3Jvb20tbmV4dCIsImlhdCI6MTUyMjU5NzQ1MiwibmJmIjoxNTIyNTk3NDUyLCJleHAiOjE1MjMyMDIyNTIsImRhdGEiOnsidXNlciI6eyJpZCI6IjEifX19.hxaaT9iowAX1Xf8RUM42OwbP7QgRNxux8eTtKhWvEUM

Making an authenticated request

Let's try to change the title of a post with an ID of 300 as an example of an authenticated request with JWT.

In Postman, choose POST as the method and type the following endpoint:

http://example.com/wp-json/wp/v2/posts/300

Choose No Auth in the Authorization tab, and add the following in the Headers tab:

'Content-type': 'application/json', 
'Authorization': 'Bearer jwtToken' // Replace jwtToken with the actual token (the encrypted key above)

Finally, in the Body tab, select the raw and JSON (application/json) options, then in the editor right below the options type the following:

{ "title": "YES! Authenticated requests with JWT work" }

Now you can hit SEND. Look in the response tab with all the data about the post that we requested: the value for the title key should now be YES! Authenticated requests with JWT work

  • 2
    How would you distinguish between calls that must be authenticated and such that don't have to be authenticated in the back-end? – uruk Jul 11 '18 at 20:59
  • I'm also building a React app which pulls the posts data from the WordPress database using the WordPress REST API, however, I don't want to have the REST API endpoints publicly available. Is there a way to restrict access to the REST API except for my React app? – Chris Jul 12 '18 at 11:07
3

Complementing @grazianodev's answer, this is how you get your authorization token using cURL:

/**
*   Generate a JWT token for future API calls to WordPress
*/
private function getToken() {
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL,'https://site.localhost/wp-json/jwt-auth/v1/token');
    curl_setopt($ch, CURLOPT_POST, 1);

    # Admin credentials here
    curl_setopt($ch, CURLOPT_POSTFIELDS, "username=admin&password=Str0ngPass"); 

    // receive server response ...
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $server_output = curl_exec ($ch);
    if ($server_output === false) {
        die('Error getting JWT token on WordPress for API integration.');
    }
    $server_output = json_decode($server_output);

    if ($server_output === null && json_last_error() !== JSON_ERROR_NONE) {
        die('Invalid response getting JWT token on WordPress for API integration.');
    }

    if (!empty($server_output->token)) {
        $this->token = $server_output->token; # Token is here
        curl_close ($ch);
        return true;
    } else {
        die('Invalid response getting JWT token on WordPress for API integration.');
    }
    return false;
}

After that, send your requests with the header: "Authorization: Bearer $token"

Where $token is the token returned by the getToken() function above.

I personally use the plugin "Disable REST API and Require JWT / OAuth Authentication" to restrict API access only with the token above.

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.