About

Big Bad Robots is an indie game developer but we also do contract development. We have developed on all kinds of platforms (PC,Handheld,Consoles) but now primarily focus on iOS,Android and Unity. Contact us if you looking for developers with over 20 years experience in software and game development at biz -at- bigbadrobots.com

Implementing OpenID using PHP,JanRain and Zend

June 13, 2010terence

OpenID is being touted as the way forward in allowing the chaos of user identity management to brought to a manageable level. OpenID has been available for a while, but has finally started to build traction primarily because the “big boys” of the Internet have decided to get behind it. Unfortunately, what is being said and the reality are two different things.

Google, Yahoo, Microsoft have all setup their own “unique” way for other websites to allow access to their user data with each requiring their own login step (and appropriate logos) to sign in. My initial naive exception was that I could key in a username and password and I would instantly be logged into the website that supported “OpenID”. Sadly that isn’t so, and the mess is left to  you to implement a login system. I won’t go into the theory behind OpenId as that is already well covered by many sites including Google, OpenID itself and by various articles. I will however include a diagram which illustrates the steps behind an login process as it is useful to keep in mind when implementing it.

open id flow


Now straight to implementing a OpenID based login system using PHP. After some research on the choices for implementing OpenID using PHP, there were really only 2 libraries of consequence: JanRain’s php-openid and Zend’s OpenID. I would have loved to use Zend’s OpenID implementation because I am already using it for my database abstraction layer and Zend AMF/Auth. However in this imperfect world, I found out that the Zend implementation is doesn’t fully support  OpenID 2.0 yet and more importantly attribute exchange(AX) registration. Both Google and Yahoo do  support AX so a decision was fairly clear on which to choose.

After downloading version 2.1.3 of JanRain openid library, you are going to have to patch it to remove various warning raised when using the library is used with PHP 5.3. The library was written for PHP 4 and tries to be efficient by passing everything back by reference which in PHP 5 is the default. You can find the link for the patch here. This will patch version 2.1.3, removing the ‘&’ in the offending function returns.

The next step is make sure you install any additional components to allow php-openid to work. It’s pretty self explanatory via the documentation, although I had some problems running the “detect” php script file via the web browser and had to run it via the command line. After some light reading on how to implement AX, the next step would be to write way to store openid keys/data between authorization requests/completions using a database. The php-openid implementation has a way to use the PEAR DB abstraction layer but you need to install the PEAR system as well as the now deprecated DB abstraction layer. Instead, I opted to write a database store that used Zend DB, which I am already using together with Zend AMF/Auth.

I did this by extending the Auth_OpenID_OpenIDStore class in the library and using the code in Auth/OpenID/SQLStore.php as a basis making the appropriate changes. After some head-scratching on why a simple conversion wasn’t working, I found out that you don’t need to bin2hex data using zend want to encode it for a blob.

The next step is writing simple wrapper library for OpenID itself . The simplest way of implementing an OpenID  login using php can be broken into 2 parts, the first is the “request” php script which using my wrapper looks like this:

require_once('Login/OpenId.php');

$login = new Login_OpenId($_POST['openid_identifier']);

$request = $login->authorizationRequest();

if (!$request)
{
die("Authorization failed");
}

$login->setupRegistrationQuery();
$login->redirectProvider(OPENID_HOST,OPENID_OID_RETURN);

Basically, new and initialize the OpenID wrapper with the end point of the service provider (i.e. https://www.google.com/accounts/o8/id), setup up the AX fields you want to query and the re-direct the script to the service provider for authorization(OPENID_HOST is YOUR openid website, and OPENID_OID_RETURN is the fully qualified url ..i.e. http://websites/<directory>/script.php)

Once you are successfully authorized, control is returned what is often called the OpenID catcher that allows you to interpret the OpenID credentials and allow access to your website. With the wrapper this was reduced to:

$login = new Login_OpenId();
$success = $login->complete(OPENID_OID_RETURN);

if ($success)
{
$openid = $login->response->getDisplayIdentifier();
$esc_identity =  htmlentities($openid);

if ($login->authenticate($esc_identity,$login->registrationData['email']))
{
echo "

Welcome back,".$login->registrationData['email']."

";
}
else
{
$login->createUser();
$login->authenticate($esc_identity,$login->registrationData['email']);
}
}

You can then write the appropriate code to create a new user, prompt for additional information and setup any user data. I also used Zend Auth, so that after the authorization request, I setup my own cookies that would allow my own data to be stored during web page transitions. Another interesting place to visit is the javascript openid selector.

I have attached the wrapper and the Zend DB datastore files here. Do write or comment if you use the code. It hasn’t been production tested yet, but should be  a good basis for implementing your own openid login. Good luck.

6 responses to “Implementing OpenID using PHP,JanRain and Zend”

  1. Petr Novotný says:

    Hi,
    please check the attached file (http://www.bigbadrobots.com/tmp/php_janrain_zend.zip) – it’s 404.
    I’m looking forward to use it on my websites! 🙂
    thanks Petr

    • terence says:

      Thanks Petr,

      My ISP recently moved me to another server and the file must have gotten lost. I have updated the file for your use. Good luck on your websites.

  2. Anders says:

    Hi,

    thanks for sharing some code. However, Iam having problem getting open id (with Google regulat account) to work with my Zend application. Iam wondering if it’s the “OPENID_OID_RETURN” that causes problem. According to your description it should be a fully qualified url .i.e. http://websites//script.php
    But that’s not possible in a Zend application which uses Zend routing..is http://websites/// a valid url as well?

    Thanks in advance
    BR Anders

  3. Anders says:

    sorry for spamming again.. it should be http://website/controller/action

  4. terence says:

    As far as I know it should be the URL called after an authentication process has occurred to ‘catch’ response from an OpenID request. I have not used ZEND routing so I am unsure of any specifics that may cause it not to work unless Zend is some how re-writing the headers. Couldn’t you work around it by calling a return script then proceeding to re-direct to another URL?

  5. Anders says:

    Thanks for your help. Now I have gotten the Open ID part to work. Iam currently struggling to get the authentication with Zend_Auth to work as well. Could you provide the file admin/UserManagement.php as well? Thanks a lot.
    BR Anders

Leave a Reply

Your email address will not be published. Required fields are marked *