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.
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.