Wordpress - How to: Make JWT-authenticated requests to the Wordpress API

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


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.