Poidsy is designed to be both easy to use and easy to integrate with existing systems. This document explains the developer's interface to Poidsy, and works through modifying a basic authentication script to accept OpenID logins with Poidsy.
Before you begin using Poidsy, you need to check that your environment is supported. The easiest way to do this is to download a release of Poidsy, and view the included test.php file in your web browser. This will tell you about any problems it has encountered, and what will/will not work as a result.
The bulk of the work done by Poidsy is done by the processor.php
script. This is the file that you will be including into your login page.
The processor is designed to be invoked in response to a form submission.
At present (version 0.1), it requires that $_POST['openid_url']
is set to
the user-supplied identifier.
Once the processor has finished authenticating (or rejecting) the user's
identifier, it will supply the details in a session variable. Thus, to
actually make use of Poidsy's results, you will need to call
session_start()
on your login page (if you're not already).
While Poidsy is authenticating an identifier, the user may be redirected
between the login page and their identity provider a number of times.
Whenever the user is redirected to the login page during this process,
the openid.mode
parameter will be present.
This example will walk through adding Poidsy to an existing login form.
The system we'll be modifying currently deals with usernames and passwords.
It is assumed that the Poidsy files are extracted to a poidsy
directory in the same directory as the login file.
The example code that we'll be modifying is included below. For the sake of brevity, the specific logic of finding users, checking passwords, and actually logging them in is abstracted away.
<?PHP
if (isset($_POST['user']) && isset($_POST['pass'])) {
if (passwordMatches($_POST['user'], hashPassword($_POST['pass']))) {
setUser($_POST['user']);
redirectAndExit();
} else {
define('ERROR', 'Invalid username/password combination');
}
}
if (defined('ERROR')) {
echo '<div class="error">ERROR: ', htmlentities(ERROR), '</div>';
}
?>
<p>Enter your details below to login:</p>
<form action="login.php" method="post">
<label>Username: <input type="text" name="user"></label>
<label>Password: <input type="password" name="pass"></label>
<input type="submit" value="Login">
</form>
The first step is to provide users with a second form to enter their OpenID identifier in. It's good practice to include a little OpenID logo in the input field, so users can instantly see that it's for an OpenID identifier. Poidsy handily comes with such a logo.
The following code is added below the existing form:
<p>Alternatively, login using an OpenID identifier:</p>
<form action="login.php" method="post">
<input type="text" name="openid_url"
style="background-image: url('poidsy/openid.gif') no-repeat;
padding-left: 20px;">
<input type="submit" value="Login">
</form>
As described above, Poidsy uses sessions to track data and return its
results. As our login form currently doesn't use sessions, we need to
add a call to session_start();
before we'll be using
Poidsy or its results.
The session start code therefore needs to be added before the main if statement.
<?PHP
session_start();
if (isset($_POST['user']) && isset($_POST['pass'])) {
The next step is to include Poidsy's processor when there's processing to be done. This is either when the user has just submitted the OpenID form, or when they've been redirected back from their provider during the authentication process.
We prepend the following conditions to the start of the if statement to include the processor when neccessary. Note that PHP translates the openid.mode argument to openid_mode.
session_start();
if (isset($_POST['openid_url']) || isset($_REQUEST['openid_mode'])) {
// OpenID login attempt
require('poidsy/processor.php');
} else if (isset($_POST['user']) && isset($_POST['pass'])) {
Just like normal login attempts, OpenID authentications can fail for a variety of reasons (such as the identifier not being a valid OpenID endpoint, or the provide refusing to authenticate the client), so we need to handle errors and display them to the user.
If an error is encountered, Poidsy will have set the
$_SESSION['openid']['error']
variable with a description
of the problem. We simply check for this and pass it on to the user:
require('poidsy/processor.php');
} else if (isset($_SESSION['openid']['error'])) {
// Failed OpenID login attempt
define('ERROR', $_SESSION['openid']['error']);
unset($_SESSION['openid']['error']);
} else if (isset($_POST['user']) && isset($_POST['pass'])) {
The final thing to do is to handle the case when a user has successfully authenticated themselves using an OpenID identifier. In a typical environment this will be a two-step process: creating a new account for the user if they haven't previously logged in, and then logging the user in to their account.
The following code adds another branch to our if statement:
unset($_SESSION['openid']['error']);
} else if (isset($_SESSION['openid']['validated']) && $_SESSION['openid']['validated']) {
// OpenID authentication successful
if (!isAccount($_SESSION['openid']['identity'])) {
// Create an account if they need one, using a fake
// password hash so users can't login normally
createAccount($_SESSION['openid']['identity'], 'invalid'):
}
setUser($_SESSION['openid']['identity']);
unset($_SESSION['openid']['validated']);
redirectAndExit();
} else if (isset($_POST['user']) && isset($_POST['pass'])) {
Hopefully this document has given you a sense of how to use Poidsy. It is designed to work transparently with your existing applications, and as demonstrated above can be integrated in five simple steps.
Note that, of course, how you implement Poidsy very much depends on your existing system and your requirements. If you are going to switch to using just OpenID, there is obviously no need to deal with password hashes as was done in this example, and you could in fact not use a backend database at all for your users — just rely on Poidsy to populate the $_SESSION['openid'] array.
If you're using Poidsy (or are trying to but are having problems) then I'd love to hear from you. My contact details can be found on my personal website.
You can define a set of constants to control the behaviour of Poidsy. These should be defined before the processor is included.
From Poidsy 0.1:
From Poidsy 0.2:
From Poidsy 0.3:
true
,
Poidsy will error if the provider requires interaction, otherwise Poidsy
will send a setup request. Previous behaviour always errored.
As of Poidsy 0.3, each error has an associated errorcode that defines the type of error. These error codes are: