How to set up API server with Slim and WordPress

Post written by Krasen Slavov
On Friday, April 17th, 2020

In this quick tutorial, I will show you how to use the Slim framework to set up an API server and authenticate users with their WordPress login credentials.

I am going to demonstrate this using the Slim v3 but the same approach can be easily converted with the latest version of Slim.

Before we move any further you must check that you have Composer installed on your system. For authentication, we are going to use the HTTP Basic Authentication Middleware by Tuupola.

There is a GitHub repository where you can download a working version with everything from this tutorial at https://github.com/krasenslavov/api-server-slim-wordpress

So, let us get started.

The Setup

First, we need to create api/ directory at the top level of our WordPress installation and set up a subdomain for the API server (e.g. https://api.example.com)

Then, create composer.json and run the composer update command from the terminal inside the directory with this file.

{
  "require": {
    "slim/slim": "^3.0",
    "tuupola/slim-basic-auth": "^2.0"
  }
}

This will download all the required packages and create the dependencies inside the vendor/ folder.

The Structure

Next, you should create another two files inside the api/ directory; index.php where we will add the code for our API server and .htaccess which will be used to set up our server pretty URLs (If you are running Nginx instead of Apache you should check the Slim User Guide for more information on web servers).

Now, your API directory structure should look like the example below.

public/
  api/
    vendor/
    .htaccess
    composer.json
    composer.lock
    index.php
  wp-load.php
  ...
  (all other WP files and folders)

And the content of your .htaccess file should be as follows:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]

Note: vendor and composer.lock are generated when you run the composer update command.

The Code

First, we load up our WordPress files and all the packages from the vendor/ directory.

// Load up WordPress.
require_once '../wp-load.php';
// Autoloader for Composer with (all packages and dependencies).
require_once 'vendor/autoload.php';

Next, we select all subscriber users and put their users and passwords into an array. You can do the same with any other WordPress user level, even custom once.

// Get all WordPress users with role subscriber.
$users = array();
$subscribers = get_users(['role__in' => ['subscriber']]);

foreach ($subscribers as $subscriber) {
  $users[$subscriber->user_login]['password'] = $subscriber->password;
  $users[$subscriber->user_login]['display_name'] = $subscriber->display_name;
}

Now we are ready to create the instance for our Slim app and add the authentication.

There are a couple of things you should change based on your set up. If you are loading the API form a subfolder and not a subdomain you must change the base path accordingly.

Also, if you are testing this on a localhost where you don’t have an SSL certificate installed you should change the security to false.

Lastly, since our WordPress passwords are hashed with password_hash() function we can easily verify user input using the password_verify() function.

// Instantiate Slim PHP framerwork.
$app = new Slim\App();

// Basic authentication.
$app->add(new \Slim\Middleware\HttpBasicAuthentication(array(
  'realm'  => 'Protected',
  // Restricted folder.
  // For your setup may need to add `/api` as your restricted folder.
  'path'   => '/', 
  // Working over HTTPS for improved security.
  'secure' => true,
  // All register users (out of WordPress).
  'authenticator' => function ($arguments) use($users) {
    if (password_verify($arguments['password'], $users[$arguments['user']]['password'])) {
      return true;
    }
    return false;
  },
  // Use to return an error message if the auth fails.
  'error'  => function ($request, $response, $arguments) {
    $data = [];
    $data['status'] = 'error';
    $data['message'] = $arguments['message'];
    $body = $response->getBody();
    $body->write(json_encode($data, JSON_UNESCAPED_SLASHES));
    return $response->withBody($body);
  }
)));

Note: In addition, adding the error option at the end will help us handling error messages and debugging.

The Routes

We are almost there, once the user is authenticated they should be able to access any information either pulled out of the database or generated within our PHP code. And of course, run the API server that we build.

For this, we need to set up different routes. The example below will greet the user by their WordPress display name and return the result into JSON format.

// Define app routes.
$app->get('/hello', function ($request, $response, $arguments) use($users) {
  $header = $req->getHeaders();
  $http_auth_user = $header['PHP_AUTH_USER'][0];
  return $res->withJson([
    'greeting' => 'Hello, ' . $users[$http_auth_user]['display_name']
  ]);
});

// Run the app.
$app->run();

You can open https://api.example.com/hello to test your API if you get something like the following after successful authentication then your API server is working fine.

{"greeting": "Hello, Krasen"}

What’s Next?

This was just an introduction if you are interested in a more complex example head over the 3-part tutorial I put together where you can learn How to add License Key Feature to your Premium WordPress Theme or Plugin.

Questions?

If you have any additional questions don’t hesitate to contact me at @krasenslavov or use the comments section below. I am currently working as a WordPress developer and using my expertise to help clients at Codeable.io.

About the Author:
My name is Krasen and I run the Choppr since 2007; I write WordPress related tutorials at CTRLS | DEV blog and maintain a few open-source WordPress plugins and themes at Developry.

Signup and get started with Inbound Now

Sign Up for Free

Download

[gravityform id="3" name="Popup Form" title="false" description="false" ajax="true"]