Adventures in OpenID and Zend Framework

I’ve been toying around with OpenID and the Zend Framework for a night or two now, and I’ve made a few experiences I thought I should share with the intarwebs (now, that’s probably the point where you should make the decision to stop reading for most blog posts). Quite some time has passed since I last had anything to do with OpenID, so just getting up and running was a challenge.

An OpenID identifier is usually represented by an URL (such as https://me.yahoo.com/<login>), which the OpenID consumer then contacts to get information about how to communicate with the OpenID identity provider (Yahoo! in this case). The consumer contacts the provider, gets an URL to redirect the client to, and receives notice after the client has authenticated with the provider.

First I’d like to say that OpenID seems to be too hard to use for any other than those who have a particular interest in it. I have a Yahoo! account and a Google Account, which both can be used for OpenID authentication. I have no idea how I use my Google Account for this, without having to provide endpoints manually. Ugly.

I did at least get the Yahoo! authentication working, but I’m still undecided on wether I’m going to implement OpenID support in any current project. Possibly. We’ll see.

Anyways, my implementation in Zend Framework is mostly a copy of the tutorial in the ZF manual, but there is one important point that they do not mention: In the standard installation, you have to use Zend_Session to handle your sessions. That means calling Zend_Session::start() instead of session_start(), as Zend_Session cannot be used after a session has been started. This dependency kind of killed my enthusiasm, as we just pull the parts of Zend Framework that we need into our project as thing progresses. Changing how we use sessions is a bit too much to ask. Luckily you can still use $_SESSION as usual after starting Zend_Session, but sitll. Not too fond of that. I hope that it will be decoupled some time in the future..

Testing code:

require_once 'Zend/OpenId/Consumer.php';

$consumer = new Zend_OpenId_Consumer();

if (!empty($_POST['openid_identity']))
{
    if(!$consumer->login($_POST['openid_identity']))
    {
        die("OpenID login failed.");
    }
    else
    {
        print('We logged in!');
    }
}

if (isset($_GET['openid_mode']))
{
    switch($_GET['openid_mode'])
    {
        case 'id_res':
            $consumer = new Zend_OpenId_Consumer();
            $id = false;
            
            if ($consumer->verify($_GET, $id))
            {
                $status = "VALID " . htmlspecialchars($id);
            }
            else
            {
                $status = "INVALID " . htmlspecialchars($id);
            }

            print($status);
            break;

        case 'cancel':
            print("someone pressed cancel!");
            break;
    }
}

Switch out $_POST[‘openid_identity’] with your OpenID identifier (the whole URL), and you should be all set.

If you keep getting failed logins without a redirect, check that you have https support in PHP through openssl (the module is named php_openssl). Zend Framework provides no hint that this can be a problem, but after stepping through the source (I’m test driving NetBeans 6.5) the solution became apparent.

3 thoughts on “Adventures in OpenID and Zend Framework”

  1. I wrote Dmitry Stogov, the original author of Zend_OpenId, with a link to this blog. Here’s his reply:

    Hi Wil,

    Wil Sinclair wrote:
    > Hey Dmitry, some blog feedback I found for Z_O:
    > http://e-mats.org/2008/11/adventures-in-openid-and-zend-framework/

    Thank you for forwarding this link.

    > First, is Z_O really dependent on Zend_Session?

    Yes. Both Consumer and Provider uses Zend_Session to save some data between requests. I think it’s possible to make Consumer detect regular sessions an use them. I’ll try to do it at the end of this week.

    > Second, if mod_openssl
    > is required, it seems that we should add it to the requirements
    > section
    > here: http://framework.zend.com/manual/en/requirements.extensions.html.

    OpenId can work without ext/openssl, but with ext/hash or ext/mhash and ext/bcmath or ext/gmp. However to access https:// URLs we definitely need ext/openssl.

    Thanks. Dmitry.

  2. Thanks for the reply Wil, and thanks to Dmitry for the quick update on the issue. I have no problem with the dependency on ext/openssl for https URLs, the issue is mainly that the OpenId library simply catches the exception and returns false — without giving a proper reason if you check out the error message (which will simply say that discovery failed, which can be a number of different issues).

    I’ll see if I can create a patch to provide fallback to cURL if available and setting a better error message if we’re unable to handle the issue properly.

Leave a Reply

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