Getting Started with OpenID and PHP

Out Of Memory

Something odd happened the other day. I Webbed over to a site that I visit on an irregular basis, signed in with my username and password, and hit the submit button. After a few seconds of clicking and grinding, the machinery informed me that my password had failed verification. Puzzled, I tried a few more times but, encountering zero success, stamped my heel, uttered a few creative curses and moved on to more productive work. It was only later, after submitting to various security questions and recovering my original password, that I realized my goof-up: I’d used a password belonging to another site by mistake!

If this story sounds familiar to you, that’s because it’s the story of today’s Web: too many sites, too many usernames, and not enough cranial capacity to file them all accurately. But there’s good news at hand: OpenID, a free, open-source framework for “single sign-on” across different Web sites and applications. The even better news? There already exist a bunch of PHP widgets that allow developers to easily integrate OpenID into a PHP application, and this article is going to show you how to use them. So what are you waiting for? Flip the page, and let’s get going!

Digital Me

Before diving into the code, let’s spend a few minutes answering a basic question: what’s this OpenID thing anyway and how does it work?

According to the official OpenID Web site OpenID is

“a free and easy way to use a single digital identity across the Internet”. Fundamentally, an OpenID is a customized URL, chosen by you as your online identity and registered with an OpenID service provider. Whenever an external site needs to verify your identity for login purposes, you supply this URL instead of your username; the site then contacts your OpenID service provider for authentication.

What’s the benefit? Simple: because your OpenID is stored with your OpenID service provider and any site can contact this provider to authenticate you, there’s no need to create multiple accounts or remember multiple usernames and passwords for different sites; all you need is a single OpenID. This assumes, of course, that the external site supports the OpenID framework; adoption of this is gradually increasing, and the OpenID Web site has some interesting information about various large organizations that have begun using the framework.

Typically, there are two parties to an OpenID transaction: Consumer and Provider. A Provider is like a registrar: it allows users to create and register OpenID URLs and manage their OpenID accounts, and it also authenticates the user to Consumers on demand. A Consumer (also sometimes called a Relying Party) is an OpenID-enabled Web site.

The OpenID framework is completely open-source and any Web site can become a Consumer or a Provider of OpenIDs without incurring any costs on licensing fees. As a result, there are already a large number of OpenID Providers on the Web, and a growing number of Web sites have begun allowing users to sign in to their services using an OpenID.

What happens in an OpenID transaction? Well, when a user tries logging into a Consumer site with an OpenID, the Consumer contacts the Provider to verify the user’s credentials before allowing him or her access. The user may be redirected to the Provider and asked to sign in to his or her account with the Provider using a password; once this is successfully done, the Provider automatically redirects the user back to the Consumer site, which now treats the user as verified and grants him or her the necessary access. A shared key, known to both parties and protected with strong encryption, is used throughout to maintain the integrity of the transaction and avoid “spoofing”.

If you’re new to OpenID, the information above should be sufficient to explain the basic concepts and ensure that you can follow the material that comes next; however, if you want/need a more detailed description, I’d recommend that you take a look at the OpenID developer site, at and the OpenID 1.1 specification.

Assembling The Pieces

Now that you’ve (hopefully) understood the basics of how the OpenID framework works, let’s turn to a more pressing question: where does PHP fit it? Well, there are a number of OpenID libraries written for PHP, and designed to help developers quickly add OpenID support to their Web application. This tutorial discusses two of them:

  1. The PHP OpenID Library, maintained by JanRain Inc. (JanRain Inc. also operates, a popular provider of OpenID identities). This is a stable implementation for both client and server ends of an OpenID connection, and it’s used in most of the examples in this tutorial.
  2. The Authentication::OpenID_Consumer PEAR package, proposed by Pádraic Brady. It should be noted that this package is still in proposal stage at the time of writing and should be considered alpha-state code; it’s used briefly in this tutorial to illustrate an alternative implementation to the JanRain library.

In case you don’t already have them, you’ll also need to download and install the following PEAR packages:

You can install these packages manually, or using the PEAR installer, as below:

In order to try out the examples in this tutorial, you’ll also need your own OpenID. Get one from or any other OpenID service provider (and remember that you can also use it on any OpenID-enabled Web site!). If you use the MyOpenID service, your OpenID will probably be in the form, and will be generated for you free of charge.

Once you’ve got all the pieces together, you’re ready to go. But before you flip the page, I should make one rather important disclaimer: I’m not an expert on OpenID and this tutorial isn’t intended to be an exhaustive reference to OpenID integration (specifications and client libraries change too quickly to even attempt such a lofty goal). Rather, it’s intended as a general introduction for PHP developers who are new to OpenID, to give them a broad idea of how PHP/OpenID integration works and increase their comfort level with the technology. For this reason, I’ve kept the code listings fairly simple; remember that you can always find more complex code examples in the documentation supplied with the client libraries mentioned previously.

With that caveat out of the way, let’s get started!

First Steps

The first thing you’ll need, if you’re going to begin accepting OpenIDs on your Web site, is a sign-in form. Here’s the code:

Here’s what the form looks like:

You’ll notice that this sign-in form doesn’t include a field for the user’s password. This is because, under the OpenID framework, authentication is handled by the OpenID Provider; all the user needs to access a Consumer site is his OpenID.

When the user submits this form with his or her OpenID, the form processor needs to locate the OpenID Provider and redirect to the Provider for authentication. The PHP OpenID Library can take care of this for you; consider the next listing, which wraps the form above in a conditional test and adds in the code that runs on form submission (I’m assuming here that your site – the Consumer site – is located at, but feel free to change this to http://localhost for testing purposes):

As explained previously, authentication with OpenID is a two-step process: first, the Consumer contacts the Provider with the user’s OpenID and then, the Provider performs authentication and returns control to the Consumer to complete the authentication process.

The script above performs the first step of this process. Once the form is submitted and validated, a new PHP session is started and two object instances are created: Auth_OpenID_FileStore and Auth_OpenID_Consumer. The Auth_OpenID_FileStore represents a disk location that the PHP OpenID Library will use to store data relating to the current authentication attempt; the object constructor should be passed the name of the directory to use (it will attempt to create this directory if it doesn’t already exist). The Auth_OpenID_Consumer object represents an OpenID Consumer, and its constructor is passed the Auth_OpenID_FileStore object generated in the previous step.

To begin the sign-in process, the script calls the Auth_OpenID_Consumer object’s begin() method, passing it the user’s OpenID. The return value of this method is an Auth_OpenID_AuthRequest object, which represents an authentication request. This object’s redirectURL() method is then invoked with two arguments: the URL used to identify your site to the OpenID Provider, and the URL to which the OpenID Provider should return control post-authentication. The return value of redirectURL() is a URL string, which is used to redirect the user’s browser to the OpenID Provider’s Web site.

At this point, control transfers to the OpenID Provider, which may require the user to authenticate himself or herself using a password. Once this process is completed, the OpenID Provider redirects the user’s browser back to the URL passed as second argument to the redirectURL() method – in this example, the script oid_return.php on the Consumer’s domain. Typically, the OpenID Provider will also attach various bits of information to the query string as GET parameters; these are used by the Consumer to complete the authentication process.

Let’s now look at what the oid_return.php script does:

The first half of this script is similar to what you’ve previously seen: it initializes the storage area and creates a new Auth_OpenID_Consumer object. It then calls the object’s complete() method, passing it the URL string that the OpenID Provider redirected to; the return value of complete() is an Auth_OpenID_ConsumerResponse object, which represents the response of the OpenID Provider to the authentication request. Four response codes are possible: Auth_OpenID_SUCCESS, which indicates that authentication was successful; Auth_OpenID_FAILURE, which indicates that authentication failed; Auth_OpenID_CANCEL, which indicates that the authentication request was cancelled by the user; and Auth_OpenID_SETUP_NEEDED, which only appears if the OpenID server was asked to authenticate non-interactively but was unable to do so.

In our example above, once authentication is complete, a session variable named $_SESSION[‘OPENID_AUTH’] is initialized with a Boolean value indicating whether authentication was successful or not. It’s now easy to use this session variable for page-level authentication, by looking for it in every restricted page of the site, and only allowing the user access if this variable is set to Boolean true. Here’s a simple example of how this could be implemented in one such restricted page (restricted.php):

If a user attempts to access such a restricted page without successfully authenticating his or her OpenID, $_SESSION[‘OPENID_AUTH’] will either not exist or be false and the user will simply see an error message. It’s only after successful authentication with the OpenID Provider, that $_SESSION[‘OPENID_AUTH’] will become true and the user will be able to view the content of the restricted page.

Keeping It Simple

When you sign up for an OpenID, chances are that you’ll have been asked for optional profile information, including your name, email address, language and country of residence. The OpenID specification includes a provision for Consumers to retrieve this profile information from a Provider during the authentication process. This so-called Simple Registration extension is fully supported in the PHP OpenID Library, and the following revision of the previous example illustrates its usage:

In a Simple Registration request, a Consumer can ask for any or all of 8 pieces of information: nickname, email address, full name, date of birth in YYYY-MM-DD format, gender, postcode, country of residence, language and time zone. Each of these is represented by a key: for example, ‘dob’ for date of birth, or ’email’ for email address.

To create a Simple Registration request using the PHP OpenID Library, call the Auth_OpenID_SRegRequest class’ static build() method with two arrays as argument: the first array lists required keys while the second lists optional keys. In the example above, the user’s full name, date of birth and language are required, and the user’s nickname is optional.

Assuming authentication succeeds, the profile attributes requested, if available with the OpenID Provider, are returned to the Consumer with the other query string parameters. They can then be retrieved as an associative array, by initializing an instance of the Auth_OpenID_SRegResponse class with the response packet and then calling the instance’s contents() method, as illustrated below:

It’s now easy to use this profile information within the Consumer site’s workflow – for example, to automatically register the user ‘s account using his name, or to send an email to his email address. To illustrate, consider this enhancement of the previous script, which uses the email address retrieved from the OpenID Provider to check if the user already has an account on the Consumer’s system. If the answer is yes, a personalized welcome message is printed with the user’s email address; if not, a new user registration form is generated, with the fields pre-filled with data retrieved from the user’s profile. Here’s the code:

Here’s what a user with an account on the system would see after signing in with an OpenID:

And here’s what a new user would see after signing in with an OpenID:

A Question Of Storage

The previous examples have all used PHP OpenID Library’s file storage class for local storage of OpenID data. If this is not to your taste, you can also store OpenID data in a MySQL, PostgreSQL or SQLite database, by replacing the Auth_OpenID_FileStore object with Auth_OpenID_MySQLStore, Auth_OpenID_PostgreSQLStore or Auth_OpenID_SQLiteStore objects respectively.

The following example illustrates, using a MySQL database for storage:

To use a MySQL database for storage, initialize an Auth_OpenID_MySQLStore object and pass the object constructor a PEAR DB connection handle to the database. Calling the object’s createTables() method takes care of initializing the necessary database tables, and the remainder of the script proceeds as before. When processing the data returned by the OpenID Provider in the return script oid_return.php, remember to again use Auth_OpenID_MySQLStore instead of Auth_OpenID_FileStore.

Incidentally, if you wish to use a custom database abstraction library instead of PEAR DB, you can do this by subclassing the Auth_OpenID_DatabaseConnection class and using it with your custom abstraction toolkit. Similarly, if you’d prefer to use a storage mechanism other than files or SQL databases, you can use the Auth_OpenID_OpenIDStore class as the basis for your custom store. For more information on this, look in the documentation for the JanRain PHP OpenID Library.

An Alternative Approach

An alternative OpenID Consumer implementation is that provided by the Authentication::OpenID_Consumer PEAR package, currently in proposal status. At the time of writing, this is alpha-quality code, but it’s interesting to see it in action nevertheless (note that you might need to set PHP’s error reporting level to ignore warnings and notices thrown by the package; this should be fixed in the final release). Consider the next listing, which is equivalent to the first example in this tutorial:

Apart from the differences in notation, this is remarkably similar to what you saw in previous examples: the script creates a file store, initializes a Consumer object with the store, and then calls the Consumer object’s start() method with the user-supplied OpenID to begin the authentication process with the OpenID Provider. The resulting Authorisation object’s redirect() method, which accepts both the return URL and the site identifier, then takes care of redirecting the user’s browser to the OpenID Provider’s Web site.

Once the user completes authentication, the OpenID Provider returns control to the Consumer script oid_return.php:

Here, the Consumer object’s finish() method is used to complete the authentication process. The result of the finish() method is a Response object, representing the response send by the OpenID Provider to the Consumer’s authentication request. This object’s getResult() method can be used to test the result of the authentication process, and take appropriate action depending on whether the result is successful or not.

Service With A Smile

Now that you’ve seen two different implementations of an OpenID Consumer, let’s turn our attention to the Provider end of the connection. First, it should be noted that the JanRain PHP OpenID Library discussed earlier in this article also includes a full-fledged OpenID Provider implementation, which you can use to custom-code your own OpenID server. An example server is included in the package archive to get you started.

In most cases, however, you can get away without coding your own OpenID Provider, especially if your needs are simple. There are a number of open-source packages that allow you to set up and manage an OpenID server “out of the box”; here’s a quick list:

And that’s about it for this article. Over the last few pages, I gave you a crash course in OpenID, explaining what it was and how it worked. I then coerced you into installing some PHP-based OpenID libraries, and showed you how you could use them to add OpenID support to your Web application. I also explained the Simple Registration extension to OpenID, showing you how it could be used to retrieve a user’s profile from an OpenID Provider and inject that data into your Web application. Finally, I demonstrated an alternative, PEAR-based implementation for OpenID Consumers, and pointed you to some easy-to-install-and-use scripts for setting up your own OpenID server.

If you’re interested in learning more about PHP and OpenID, also consider the following resources:

Have fun, and happy coding!

Copyright Melonfire, 2007. All rights reserved.