Getting started with the Yahoo! Address Book API

If there’s one internet application that people use most, it's probably email. However, email is worthless if you don't know where to send your messages and who you’re sending to; this makes the email address book one of the most widely used applications as well. In fact, the Yahoo! Address Book is a gold mine of relationships, connections, and history waiting to be tapped. To unlock that value, we’ve opened the Yahoo! Address Book to third-party developers.

This tutorial is aimed at helping new developers with a background in PHP get started with the Yahoo! Address Book APIs. I assume no prior knowledge of Yahoo technologies, but I do assume that you are familiar with network programming and understand how HTTP works at a basic level.

Before you get started, you’ll need an AppID (application identifier) from developer.yahoo.com (https://developer.yahoo.com/auth/appreg.html) with the correct scope of Address Book Read.
(Note: Sign up for an AppID at: https://developer.yahoo.com/wsregapp/)

For this tutorial to work, when you obtain your AppID, specify your application entry point to be:

http://www.domain.com/auth/bbauth.php

Substitute your own domain for www.domain.com. This structure will help you consolidate your landing pages (for Yahoo! and any other web services you choose) when you start building apps that rely on passing credentials to a receiving web page. The tutorial also assumes that you have access to an installation of PHP4 or PHP5 that is curl -capable.

When you are done with this tutorial, you should know how to do the following:

1) Present a user with a signed URL to login and pass user specific credentials back to your application.
2) Understand how to accept the user credentials and use them to make an authenticated call to the Y! Address Book APIs and get access to their data.
3) Use the built-in PHP SimpleXML() call to obtain specific fields from the user's address book.

Charles Wu
Platform Product Manager


Authentication

The Yahoo! Address Book API uses BBAuth, which relies on signed URLs to verify that legitimate parties are accessing a user's data. BBAuth uses a combination of a shared secret, cookies, and time-stamp to ensure that a user's data cannot be easily accessed. These checks protect the user, but can seem complex; many new developers struggle at this step to create a correctly signed URL.

This tutorial will not go into detail about the signing mechanics of how the authorization scheme works. Instead, I’ll rely on the “quick-start” PHP BBAuth libraries provided by Yahoo! at developer.yahoo.com. For developers who want a deeper understanding of BBAuth, please visit: https://developer.yahoo.com/auth/user.html.

My demo application will output the emails in a user's Yahoo! Address Book. It will have an HTML wrapper with a DIV to display the content depending on whether it’s a BBAuth-authenticated page or not. The wrapper code is pretty uninteresting, I’ve listed it here :


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<div id="look">
<h2>Address Book Tutorial Blog Post</h2>
<div>
<?php CreateContent(); ?>
</div>
<div id="content">
</div>
</div>
</body>
</html>

The interesting stuff is created in the CreateContent() call. Once it determines whether you’ve already authenticated, it gets the data. The pseudo-code is as follows:


if (empty($_GET["token"])) {
// User is not coming from BBAuth because it has not been called with a parameter "token" PRESUMABLY from BBAuth.
// Create a link for the user to log into BBAuth
} else {
// User is presumably being redirected from BBAuth
// so create an authenticated URL and get the address book data.
}

The key (no pun intended) in BBAuth is the pairing of the AppID (which can be publicly visible) and the shared secret (which should be kept hidden). These two cryptic strings are used to authenticate who you are. All your calls use some combination or transform of these items to demonstrate who you are. BBAuth also relies on time-stamps to make sure that a fresh call is made. I won’t apply the transforms directly, but instead will rely on PHP libraries from developer.yahoo.com and available in the BBAuth Quick Start bundle at: https://developer.yahoo.com/auth/quickstart/bbauth_quickstart.zip

Since these are global to everything we do, let's make them available to the page, and since they won't change, let's define them as constants.


define("APPID", '***-YOUR+APPID+HERE-***');
define("SECRET", '***-YOUR+SHARED+SECRET+HERE-***');

Next, we'll include the correct BBAuth library. We'll assume that it's in the same directory as this script, but you can modify the path to meet your needs. This library includes auth routines for the different types of APIs Yahoo! offers.


// Include the proper class file
$v = phpversion();
if ($v[0] == '4') {
include("ybrowserauth.class.php4");
} elseif ($v[0] == '5') {
include("ybrowserauth.class.php5");
} else {
die('Error: could not find the bbauth PHP class file.');
}

...

// Initialize the Authentication Object

$authObj = new YBBauthREST(APPID, SECRET);

The demo script here does double duty: one part constructs a URL that directs a user to a login page for BBAuth and another uses the BBAuth token to make the actual API calls. Normally, your app would construct the login URL in one page, and then redirect to another page to collect the authorization token. Other applications choose a single page to handle the application flow and authentication. In this case, we use a single page.

Creating the Login URL

Assuming you don't have a token you’ll have to direct the user who is accessing your app to the correct page. The YBrowserAuth class has a single call that will generate the correct URL based on your credentials and the current time. The call is:


YBrowserAuth->getAuthURL('your_app_data', RETURN_USER_HASH boolean)

You'll want the RETURN_USER_HASH set to true to return the user token when completed. This user token is unique to the user who logs in and can be used to associate your application user data with the Yahoo! login. (This is similar to the user info that OpenID provides.) This token returns a signed URL that can be embedded in the page, where a user can click it to authenticate.


// You can send some data along with the authentication request
// In this case, the data is the string 'some_application_data'
echo 'You have not signed on using BBauth yet<br /><br />';
echo '<a href="'.$authObj->getAuthURL('some_application_data', true).'">Click here to authorize</a>';

The 'your_app_data' is a user-provided switch that your landing endpoint can use to direct to the correct function, for instance, if your web application uses both the Address Book API and the Mail API. If you come in from a point in your app that’s using Mail, you could pass the parameter 'mail' and your landing page will store the token. You can store it in a database and then redirect to the page that processes the mail API calls. If you’re coming from a place where the app needs to initiate an address book call, you can use 'addressbook' as the parameter and do a switch based on that.

Calling the Address Book

If a user clicks on the link generated above, they’ll be directed to a special Yahoo page and asked to enter user name and password on Yahoo!. The information in the URL means that once they’ve verified that your app is permitted to access their Contacts information, their browser is redirected to the landing page you provided when you got your AppID.

Yahoo! passes you a token that can be used for two weeks or until the user revokes permission. We pass that token via a GET parameter called "token." We also pass back the app data information you may have sent in the GET parameter called "appdata."

First, validate that the token you receive is correct. The validate_sig() call of the YBrowserAuth class extracts the appropriate information to ensure that the source and contents are from Yahoo!. Let's assume that this is correct. Now it’s time to get the address book data.

Constructing the Web Services Call

You need to construct an Address Book API query. The query structure is very similar to an SQL query, so it's easy. Start off with the root:



http://address.yahooapis.com/api/ws/v1/searchContacts?

Next, pick the data format you want for the return data. In my example we use XML. You can also specify JSON.


format=xml

Next, determine what fields you want returned. If you leave this out, you’ll get all fields for all contacts. In this example we only want email addresses to kickstart our invitation flow.


&fields=email

Finally, determine the search criteria you wish to apply. In this case, we only request contacts that have an email address.


&email.present=1

The completed query will look like this:



http://address.yahooapis.com/api/ws/v1/searchContacts?format=xml&fields=email&email.present=1

Note: Making a curl call on this will give you a 403 forbidden error. To make the call you now need to perform the same signing process as you performed to request the login URL. Your app makes a call to obtain a WSSID (Web Services Session ID) and the user's cookies. This is a limited time Session ID. In addition, you need to set the cookie. This additional step protects you and your users. The Ybrowserauth class provides a mechanism for that in the form of the makeAuthWSgetCall() that signs the URL, and returns what’s received from the web service.


$xmlstr=$authObj->makeAuthWSgetCall($path);

This sample code displays the information you received from the authentication web service for your information. We'll skip that here. You now have an XML file that can be parsed. The rest is standard PHP:


$xml = new SimpleXMLElement($xmlstr);

Iterating through the array creates an array that can be manipulated. In this case, because address books can be full of duplicates, we eliminate the dupes first, to be certain we don’t spam users with multiple invites.


$i = 0;
foreach ($xml->contact as $contact) {
$emails[$i] = $contact->email;
$i++;
}
$emails = array_unique($emails);
sort($emails);

The sample file prints out the emails and you’re done. The use of some simple libraries makes it a breeze to work with the Yahoo! Address Book API. Note the code from this tutorial will be available in the files section of the ydn-addressbook Yahoo Group.

Other links that might be of interest:

[1] A common authentication problem is that your timestamp may not align with Yahoo! time. Yahoo offers a time web service that returns the current time for your purpose:

https://developer.yahoo.com/util/timeservice/V1/getTime.html

[2] YDN Evangelist Dan Theurer has blog post on his blog explaining use the of BBAuth for Single Sign On and how to use the User Hash:

http://www.theurer.cc/blog/2006/09/29/bbauth-coding-single-sign-on/