donderdag 24 april 2008

How to use secure AuthSub for GData in PHP

For some time now, Google has opened up several API's which enable you to integrate your website with several Google services. This API is called the GData API. With the GData API you can read or modify a user's Google Contacts, Google Calendar of Blogger weblog.

The Google GData API has several methods for authentication. Use can use a method with which the end-user will have to enter their username and password on your site, or you can use AuthSub.

With AuthSub a user doesn't have to enter his username and password on your own website, but has to authorize your website via the Google domain. AuthSub has two variants, you can use either the normal or the secure version.

When you are using the normal (unsecure) version, a warning is displayed when the user has to authorize your application. This warning does not appear when using the secure version. Using the secure version with PHP is quite a hassle. I will try to explain some of it's quirks in this post. Some knowledge of AuthSub and the GData API is expected.

Obtaining a users authorization

The first step is recieving the user's authorization to use the information stored in his or her Google Account. Send the user to authorization page at the Google domain: https://www.google.com/accounts/AuthSubRequest.

This page takes four parameters (passed as GET parameters):

  • next: The URL to which the user should be redirected afther authorizing your application. This should be the exact same URL as you entered at the 'Manage My Domains' page in your Google Account settings.
  • scope: this defines to what you want access (for example Google Contacts or Google Calendar). To use this for Google Contacts, set the scope to https://www.google.com/m8/feeds/. (Notice the https prefix, signalling that you want to use a secure connection. This is important but not stated in the GData API documentation.)
  • secure: set this to '1' to enable the secure variant of AuthSub.
  • session: set this to '1' if you want to issue more than one request on behave of the user (strongly recommended).

Signing a request

In order to sign a request, you have to create a X509 private key and public certificate with OpenSSL. You can download Microsoft Windows binaries for OpenSSL from the web (Most Linux distros come with pre-installed OpenSSL). Create your key and certificate from the command prompt like this (use your own domain):
C:\Openssl>openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj '/C=NL/ST=GR/L=Groningen/CN=www.example.net' -keyout privatekey.pem -out publiccert.pem.

You have to upload the public key to Google via the Manage Your Domains page. In order to sign some string in PHP you have to use the OpenSSL PHP extension. Example function suitable for the GData API:

function sign($data) {
$priv_key = file_get_contents('privatekey.pem');
$pkeyid = openssl_get_privatekey($priv_key);
openssl_sign($data, $signature, $pkeyid);
return base64_encode($signature);
}


You also need to add a random 64-bit integer to your request in order to prevent replay attacks. Since PHP is a 32 bit language, this could be a tad difficult. However, you could just create a string which looks like 64-bit integer. Just concatenate enough digits until you have something sufficiently long:

function get64BitInt() {
$int = mt_rand(1,17) . sprintf('%6d',mt_rand(0,999999999)) . sprintf('%6d',mt_rand(0,999999999));
return $int;
}

Exchanging the token for a session key

Now that you know how to sign a request, you can make the first request where you will have to exchange te authentication token for a session token.

Geen opmerkingen: