Question: Would you stop and help a cyclist carrying their bike while walking down the road?

what would you do?
what would you do?

Here I am walking down the street in Northampton in full kit with my bike slung over my shoulder. 4 Roadies, 12 bicycle commuters, and more cars than I can count passed by. Not a soul stopped or asked if I needed assistance. I was more than a little bit pissed off. I’ve stopped every time I’ve come across a fellow cyclist who looks like they are in need of help. Go figure.

Yet, there was one nice woman (who informed me she was riding around the world) that offered to help as I was fixing my first of two flats today. At that point I was okay. We had a short conversation about her trip. Looking back I should have taken the time to ask her more about her story.

Accessing an API that authenticates using the JSpring Security Model using PHP and cURL

Welcome to my first ‘Tech Talk’ post. This post will walk you through my PHP solution for accessing an API that insists on using a JSpring Security Token for authentication. In a nut shell this is a ReSTful approach with the underlying communication being accomplished using the cURL library. cURL was chosen as it has the ability to store session data within the handler object. A handy container with which to then use for subsequent calls to the API.

Let’s start with the API Controller class. This is the top level class that defines how to connect and access the APIs.

“Every API request requires an authenticated session. The caller is responsible for establishing an authenticated session and forwarding any authentication tokens with the API request. The authentication token is a J2EE JSESSIONID.” –API Authentication Requirement

To facilitate the authentication let’s start with setting a cURL POST request with the following setup options:

    // cURL options that seem to work to kick start API sign-on
    $j_spring_security_args = array(
      CURLOPT_CONNECTTIMEOUT => 60,
      CURLOPT_TIMEOUT => 60,
      CURLOPT_USERAGENT => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_SSL_VERIFYPEER => false,
      CURLOPT_FOLLOWLOCATION => true,
      CURLOPT_COOKIEFILE => '',
      CURLOPT_POST => true,
      CURLOPT_POSTFIELDS => http_build_query($this->security_data, '', '&'),
    );

The authentication request would not validate until I added the CURLOPT_COOKIEFILE option (this was not an easy find). Also take note that for ease of use I’ve created an associative array that holds the j_username and j_password information and added them into the post fields section of the options array.

With the cURL options array set, we can now call the cURL execute command and store the returned info within a variable named $result. This variable will also hold the cURL handle (holds the JSessionID cookies) that will allow us to continue to call whichever API method we choose.

// setup the cURL to post the JSpring Security credentials
$ch = curl_init($this->getApiUri() . '/j_spring_security_check');
curl_setopt_array($ch, $j_spring_security_args);

// send off the login request
$result = curl_exec($ch);
$arrInfo = curl_getinfo($ch);

// set an object to hold the requests return result
$this->cURL = array();
if ($arrInfo['http_code'] == 200 && strtolower(trim($result)) == strtolower('success')) {
  $this->cURL['handler'] = $ch;
  $this->cURL['result'] = $result;
  $this->cURL['code'] = $arrInfo['http_code'];
  return TRUE;
}

At this point we check to see if the authentication request worked. If it did, the returned http code will be 200 with success in the body. This may vary from API to API so be prepared to examine the result returned. We then set a result array which contains the cURL handle, the request result, and http code. This array can then be accessed via controllers which extend the ApiController classs.

All that is left now is to fill out the class constructor to initiate the login request:

  public function  __construct()
  {
    if (! $this->doLogin()) {
      throw new \Exception('The request requires authentication', 401);
    }
  }

If the authentication request fails, the ApiController constructor throws an Exception which will inform the end user and gracefully exit execution.

API Controller
API Controller

This diagram shows the class hierarchy I’m using to construct the controllers for use with either the ApiDocs, ApiUser, or ApiUserRoles APIs. It’s a simple relationship with each child class authenticating upon instantiation. From here we are left to flush out the details of the ReSTful representation of the API. I’ve chosen to implement each method (or verb if you will) with one of the corresponding class methods:

  • GETAction()
  • POSTAction()
  • PUSHAction()
  • DELETEAction()

Below is an example of the GETAction() within the ApiDocsController:

public function GETAction()
  {
    // cURL options to access Document Image Retrieval
    $documentImageRetrieval =  array(
      CURLOPT_URL => $this->getApiUri() . '/docs/' . implode('/', $this->imagePath),
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_HTTPGET => true,
    );

    // setup the cURL to retrieve the image
    curl_setopt_array($this->cURL['handler'], $documentImageRetrieval);
    $response = curl_exec($this->cURL['handler']); // slurp the JPG

    if (!curl_errno($this->cURL['handler'])) {
      curl_close($this->cURL['handler']); // clean up the cURL resources

      // create the image
      $img = imagecreatefromstring($response);
      header('Content-Type: image/jpg');
      imagejpeg($img);
      imagedestroy($img);
    }
  }

Here we are setting the cURL hadler to a GET action and passing along the rest of the URI to the API. In essence this is nothing more than a wrapper around the API call. I’m leaving all the heavy work up to the API and simply returning the result. From here what I’ve left up to you is to implement the remaining controllers and the associated action methods needed to access the API.

With our controllers all set for action we’re left to our own devices on how to create our controller script. I would like to build this controller in a robust fashion so that if I ever need to access additional APIs I can simply create a new controller class and call it’s action methods. I accomplished this using PHP’s Variable Variables methodology.

“Sometimes it is convenient to be able to have variable variable names. That is, a variable name which can be set and used dynamically. A variable variable takes the value of a variable and treats that as the name of a variable.” –excerpt from the PHP Manual

Sounds confusing does it not? It’s actually easier to see in an example. Below is the main body of my controller script:

  // grab incoming parameters
  $verb = $_SERVER['REQUEST_METHOD'];
  $action_name = strtoupper($verb) . 'Action';
  $path = explode('/',$_SERVER['PATH_INFO']);

  // instanciate the requested controller
  $controller_name = ucfirst($path[1]) . 'Controller';
  if (class_exists($controller_name) && method_exists($controller_name, $action_name)) {
    try {
      $controller = new $controller_name(array_slice($path, RETRIEVE_PATH));

      // call the controller's REST verb action method
      $controller->$action_name();
    }
    catch (Exception $e) { // something went wrong, inform the end user what we can
      myErrorHandler($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine());
    }
  }
  else { // inform the end user that the requested service is unavailable
    myErrorHandler(503, "Service Temporarily Unavailable", null, null);
  }

The highlighted lines from above are where I make use of variable variables. In essence I’ve set the $controller variable to ApiDocsController and the $action variable to GETAction (which happens to map to a class and class method). The compiler will see something similar to the following which looks more like how to call class constructors and methods:

    class_exists(ApiDocsController) && method_exists(ApiDocsController, GETAction);
    $controller = new ApiDocsController();
    ApiDocsController::GETAction();

Within the constructor I’m passing the rest of the URI as an array. Which will then be passed along to the API so that it may do the rest of the action. And that’s it! We’ve successfully established JSpring Security authentication to the API and are now able to make direct method calls into the API. The final piece is to take advantage of Apache’s RewriteEngine so that I might be able to translate a URI such as

    https://yourwebserver/api/docs/directory/image/

into a class constructor for the ApiDocsController controller, authenticate, and then call the GETAction method to retrieve the image from the directory directory.

I hope you find this post informative as well as helpful!

Tech Talk

Me & The Ride
Me & The Ride

I’m hoping to fill this section with fun tips and facts of what and how things I’m responsible for function.

Drupal Developer:

Investigating the use of custom Drupal modules for consumption by various departments on campus. Within about 6 weeks the team and I should have a white paper on this. Will publish it here if possible.

uPortal Developer:

Development of JSR 286 portlets using Java & Spring methodologies. I’m also the administrator for uPortal.
spend more time writing code. 😉