Fire Eagle : PHP Walkthrough

PHP Walkthrough

This page will get you started writing your first Fire Eagle application using PHP.



Setup

Background

Fire Eagle uses OAuth to identify and authenticate applications and users that interact with the system. More details about OAuth and how it's used in Fire Eagle. This walkthru will show how to get your application to authenticate a user using OAuth, then how to access Fire Eagle's API using the token obtained.

Server Setup

Before you get started, you'll need a web server running PHP5. Linux distributions generally make it available through the package system; try sudo apt-get install libapache2-mod-php5 on Debian, or yum install php5 on CentOS and friends. On Windows, try XAMPP.

The PHP OAuth library requires PHP 5.2.3, so make sure you're running at least that version. Windows users will also need to download a copy of curl-ca-bundle.crt and add a line into fireeagle.php -- see the source for details.

Create a directory somewhere web-accessible to hold the code you're about to write and a directory called app inside it. Change to the app directory and hen create a file called walkthru.php. Also create another subdirectory called lib at the same level as app. Then grab a copy of fireeagle.php and OAuth.php and drop them in the lib directory. In the end it should all look like this:

Make sure you know the URL of your walkthru.php file; you'll need it later. For example, if you're doing this on a local web server in a folder called /var/www/fe_walkthru, it might be http://localhost/fe_walkthru/app/walkthru.php.

Fire Eagle Stuff

Now you need to get your application set up with Fire Eagle, to get a consumer key and consumer secret, which you'll need for all OAuth and API requests.

First, create your application on Fire Eagle. Most of the fields you need to fill in should be fairly self-explanatory. Here are some hints for the others:

  • The answer to "What kind of authentication do you want to use?" is "Auth for web-based services". That means that you're making a website rather than a client app or something to run on a mobile phone. (More info about application types.)

When you submit the new application form, you'll get a consumer key and consumer secret -- jot those down. You can always check them again in the Manage Applications section.


Let's Write Code!

You can follow along as we build this application, or you can download the almost finished example app and figure out what's going on for yourself.

Here's what this code is going to do:

  • Get an OAuth request token from Fire Eagle.
  • Send the user over to Fire Eagle for authorization.
  • When the user comes back (via the callback URL), get an OAuth access token from Fire Eagle.
  • Once it has the access token, use the Fire Eagle API to get and set the user's location.

We're going to be lazy here and just use the PHP session ($_SESSION) to store tokens. In a real app you'd keep these in your user database for future use.


Code structure

Open your walkthru.php file in a text editor and paste in the shell of your new script, then put your consumer key and secret. Also add the URL of your walkthru.php file plus ?f=callback (something like http://localhost/fe_walkthru/?f=callback) as the callback URL. This is where the user will be sent after authorization.

<?php

error_reporting(E_ALL);
require_once dirname(__FILE__)."/../lib/fireeagle.php";

function main() {

 // hardcode your keys here
 $fe_key = 'INSERT CONSUMER KEY HERE';
 $fe_secret = 'INSERT CONSUMER SECRET HERE';
 $fe_callback = 'INSERT CALLBACK URL HERE';

 // or put them in walkthru_config.php, if you don't want to change this file
 $cfn = dirname(__FILE__)."/walkthru_config.php";
 if (file_exists($cfn)) require_once($cfn);

 ob_start();
 session_start();

 if (@$_GET['f'] == 'start') {
  // get a request token + secret from FE and redirect to the authorization page
  // TODO step 1
 } else if (@$_GET['f'] == 'callback') {
  // the user has authorized us at FE, so now we can pick up our access token + secret
  // TODO step 2
 } else if (@$_SESSION['auth_state'] == 'done') {
  // we have our access token + secret, so now we can actually *use* the api
  // TODO step 3
 } else {
  // not authenticated yet, so give a link to use to start authentication.
  ?><p><a href="<?php echo htmlspecialchars($_SERVER['PHP_SELF']) ?>?f=start">Click here to authenticate with Fire Eagle!</a></p><?php
 }
}

main();

?>

The following sections will explain each TODO block in the code.

Step 1: Get a request token, and send the user to Fire Eagle to authorize the token

To initiate the OAuth process, we first get a request token from Fire Eagle using the getRequestToken method of the FireEagle object, and stash it in the PHP session. Next, we redirect the user over to the Fire Eagle authorization URL, which you can build with the getAuthorizeURL method.

Fire Eagle will ask the user for permission to show your application their location (giving them the option of limiting the detail provided) and/or to set their location. After they confirm this, they will be redirected back to your application, and you will be able to exchange the OAuth request token for an access token, which you can use to call API methods.

Replace the first TODO comment in the code with the following:

  $fe = new FireEagle($fe_key, $fe_secret);
  $tok = $fe->getRequestToken($fe_callback);
  if (!isset($tok['oauth_token'])
      || !is_string($tok['oauth_token'])
      || !isset($tok['oauth_token_secret'])
      || !is_string($tok['oauth_token_secret'])) {
   echo "ERROR! FireEagle::getRequestToken() returned an invalid response. Giving up.";
   exit;
  }
  $_SESSION['auth_state'] = "start";
  $_SESSION['request_token'] = $token = $tok['oauth_token'];
  $_SESSION['request_secret'] = $tok['oauth_token_secret'];
  header("Location: ".$fe->getAuthorizeURL($token));

Now if you browse to the URL of your walkthru.php file, you should see a "Click here to authorize with Fire Eagle" link. Clicking the link should send you over to the Fire Eagle authorization page.

Click the "Confirm" button and you will be sent back to your script with your newly-authorized request token, with a url like walkthru.php?f=callback&oauth_token=2pj9w29i0xmp&oauth_verifier=dwlwed. Your script won't do anything yet, which brings us to ...

Step 2: Catch the callback from Fire Eagle and exchange the request token for an access token

The next step is to respond to the callback from Fire Eagle, and to exchange our request token for an access token, which we can use to call API methods. First we make a couple of checks to ensure that we really are doing an OAuth negotiation and that nothing has gone wrong with the token. Next, we call Fire Eagle with the request token (and the oauth_verifier received) and obtain an access token, using the getAccessToken method of the FireEagle object.

Finally, we stash the response (access token and secret, and info on what permissions we have) somewhere. We're just going to put it in the PHP session, but in a real application you would store this in the user database, so you can call API methods in future.

Replace the second TODO comment in the code with the following:

  if (@$_SESSION['auth_state'] != "start") {
   echo "Out of sequence.";
   exit;
  }
  if ($_GET['oauth_token'] != $_SESSION['request_token']) {
   echo "Token mismatch.";
   exit;
  }

  $fe = new FireEagle($fe_key, $fe_secret, $_SESSION['request_token'], $_SESSION['request_secret']);
  $tok = $fe->getAccessToken($_GET['oauth_verifier']);
  if (!isset($tok['oauth_token']) || !is_string($tok['oauth_token'])
      || !isset($tok['oauth_token_secret']) || !is_string($tok['oauth_token_secret'])) {
   error_log("Bad token from FireEagle::getAccessToken(): ".var_export($tok, TRUE));
   echo "ERROR! FireEagle::getAccessToken() returned an invalid response. Giving up.";
   exit;
  }

  $_SESSION['access_token'] = $tok['oauth_token'];
  $_SESSION['access_secret'] = $tok['oauth_token_secret'];
  $_SESSION['auth_state'] = "done";
  header("Location: ".$_SERVER['SCRIPT_NAME']);

Now go back to your browser window and refresh the page. It should quietly fetch an access token and redirect you back to your script's main URL (e.g. walkthru.php). Which brings us to...

Step 3: Make API calls!

Now you have an access token, so you can finally make API calls!

The FireEagle object has a call method that you can use to call any API method, and also some helper methods that handle particular methods. The walkthru code uses the user, update and lookup helper methods.

Replace the final TODO comment in the code with the following:

  $fe = new FireEagle($fe_key, $fe_secret, $_SESSION['access_token'], $_SESSION['access_secret']);

  // handle postback for location update
  if ($_SERVER['REQUEST_METHOD'] == "POST") {
   // we're updating the user's location.
   $where = array();
   foreach (array("lat", "lon", "q", "place_id") as $k) {
    if (!empty($_POST[$k])) $where[$k] = $_POST[$k];
   }
   switch (@$_POST['submit']) {
   case 'Move!':
    $r = $fe->update($where); // equivalent to $fe->call("update", $where)
    header("Location: ".$_SERVER['SCRIPT_NAME']);
    exit;
   case 'Lookup':
    echo "<p>Lookup results:</p><div><code>".nl2br(htmlspecialchars(var_export($fe->lookup($where), TRUE)))."</code></div>";
    break;
   }
  }

  ?><p>You are authenticated with <a href="<?php print htmlspecialchars(FireEagle::$FE_ROOT) ?>">Fire Eagle</a>! (<a href="?f=start">Change settings</a>.)</p><?php

  $loc = $fe->user(); // equivalent to $fe->call("user")
  ?><h2>Where you are<?php if ($loc->user->best_guess) echo ": ".htmlspecialchars($loc->user->best_guess->name) ?></h2><?php
  if (empty($loc->user->location_hierarchy)) {
   ?><p>Fire Eagle doesn't know where you are yet.</p><?php // '
  } else {
   foreach ($loc->user->location_hierarchy as $location) {
    switch ($location->geotype) {
    case 'point':
     $locinfo = "[".$location->latitude.", ".$location->longitude."]";
     break;
    case 'box':
     $locinfo = "[[".$location->bbox[0][1].", ".$location->bbox[0][0]."], ["
      .$location->bbox[1][1].", ".$location->bbox[1][0]."]]";
     break;
    default:
     $locinfo = "[unknown]";
     break;
    }
    if ($location->best_guess) $locinfo .= " BEST GUESS";
    print "<h3>".htmlspecialchars($location->level_name).": ".htmlspecialchars($location->name)." $locinfo</h3>";
    print "<ul>";
    // turn location object into array, with sorted keys
    $l = array(); foreach ($location as $k => $v) $l[$k] = $v; ksort($l);
    foreach ($l as $k => $v) {
     print "<li>".htmlspecialchars($k).": <b>".htmlspecialchars(var_export($v, TRUE))."</b></li>";
    }
    print "</ul>";
   }
  }

  if (TRUE || $_SESSION['can_write']) { // fix when we get 'writable' from the 'user' response

   ?><h2>Update</h2><p>Enter a location below and click "Move!" to update.</p>

   <form method="POST">
   <p><label for="free-text-entry">Free-text entry:</label> <input type="text" name="q" id="free-text-entry" size="40"></p>
   <p><label for="place-id">Place ID:</label> <input type="text" name="place_id" id="place-id" size="40"></p>
   <p><label for="lat">Lat:</label> <input type="text" name="lat" id="lat" size="10"> <label for="lon">Lon:</label> <input type="text" name="lon" size="10"></p>
   <input type="submit" name="submit" value="Move!">
   or just check your query: <input type="submit" name="submit" value="Lookup">
   </form><?php

  }

Now go back to your browser and refresh the page again. This time you should see the details of your location, with an 'update' form at the bottom, which lets you set your location by free-text search, Place ID, or latitude and longitude coordinates.


Finishing Up

This walkthru has demonstrated how to authorize a user and call API functions in PHP all in one script. If you're building a real application, you'll probably want to change step 2 to store the access tokens and permission details in your user database. Then instead of looking at $_SESSION['auth_state'], you can check in your database, and call API methods at any point (although we'd really appreciate it if you didn't call FireEagle to get a user's location on every page load - please cache locations for an appropriate length of time). Then you can rip out step 3 and make this script the entrypoint for Fire Eagle authorization.

Check out the rest of the developer documentation for more details on the API, the PHP code page for PHP code samples, and sign up for the Fire Eagle mailing list to talk to other Fire Eagle developers and the Fire Eagle team. Hack away!