PureID

Introduction

OpenID is a protocol for logging in to websites in a simple and secure way using identity URLs instead of emails, usernames and passwords. An identity URL is one that you control, and this ownership is verified by an OpenID provider.

PureID is an simple OpenID authentication server that allows you to be your own provider. It is a single PHP script with modest requirements.

PureID implements version 2.0 of the OpenID protocol. It is partly inspired by phpMyID, an implementation of an earlier version of the protocol which is no longer maintained.

The current version is 0.2 (track updates).

License

PureID is free software, distributed under the terms of the GNU General Public License version 3 or any later version. It is provided in the hope that it will be useful, but with absolutely no warranty. See the file COPYING for details.

Download

Program:

archive pureid-0.2.tar.gz (28.73 KB; 2011-04-20; current version)

archive pureid-0.1.tar.gz (27.19 KB; 2011-02-11; previous version)

Basic installation

Step 1: Install pureid.php.

Install pureid.php on your webserver. As an example, let's say it is installed directly in your web root and accessible as

http://example.net/pureid.php

Since it is not configured yet, this page shows an error. Access it with a “check” query to find out the details, e.g.

http://example.net/pureid.php?check

This page shows the parts that need to be configured in red. The sections “PHP” and “PHP extensions” list requirements without which PureID will not work.

Step 2: User configuration.

Configuration settings go in pureid.conf.php, for which a template is provided. After inserting correct configuration values, this file must be installed either in the same directory as pureid.php, or in /etc.

There are two settings related to the OpenID protocol:

This identity URL is used to log in to websites and is stored by websites as your unique identifier. Advanced configuration below discusses how to make it look nicer.

Step 3: Database setup.

PureID needs to store data across requests. It can use a simple SQLite database or a database server for this. The $dsn and related settings configure this.

For SQLite, $dsn contains the path of the database file. This file should be placed in a separate directory because SQLite creates temporary files there. For example,

$dsn = 'sqlite:/var/lib/pureid/pureid.sqlite';

SQLite will create the database file automatically if it doesn't exist, but the directory must exist and be writable by the webserver. If this directory is located in the web root, the webserver must be configured not to serve it.

For PostgreSQL or MySQL, first use the psql or mysql program or a web interface to create a new database. $dsn in the configuration contains the connection details and database name and $dsn_username and $dns_password contain the authentication details. For example,

$dsn = 'pgsql:host=localhost;port=5432;dbname=pureid';
$dsn_username = 'pureid';
$dsn_password = 'secret';

Once a database is configured, access the “check” page again. It should now show that it has connected to the database. This action also sets up the required tables in an empty database.

Step 4: Users and passwords.

For simplicity there is no administrative interface in PureID. Instead, connect to the database to create a new user. For SQLite this is done with the sqlite program, for PostgreSQL this is done with the psql program or a web interface.

The password is stored in hashed form. The easiest way to create this is using OpenSSL:

$ openssl passwd -1

Insert the desired username and hashed password into the “users” table in the database. For example, using SQL:

INSERT INTO users (username, password) VALUES
    ('user', '$1$YqHfLUTA$5C6WuXNMdugX2sE7.o7W0.');

Advanced configuration

Nicer URLs

The simplest way to make the endpoint URL shorter is to rename pureid.php to index.php and put it in a separate directory. This turns the URL in the example into

http://example.net/pureid/

This can also be achieved with Apache mod_rewrite. For example, with .htaccess containing

RewriteEngine On
RewriteRule ^openid$ pureid.php [L]

The endpoint becomes

http://example.net/openid

The OpenID standard requires normalizing URLs and the $endpoint setting must match the normalized URL. This means that if the URL points to a directory or to the root, $endpoint must include the trailing slash. For example, if PureID is installed as index.php in the root, logging in is possible with just

example.net

But the normalized URL will be

$endpoint = 'http://example.net/';

Identity URLs for multiple users

PureID can support multiple users, but each user must have a distinct identity URL. For this the $identity setting should include the ‘$’ character as a placeholder for the username. For example,

$identity = 'http://$.example.net/';

This allows logging in as

username.example.net

The page at the identity URL must be set up to point to the user-specific XRDS document generated by PureID with the query “xrds=username”. This can be done by inserting a X-XRDS-Location header, for example, with a simple PHP script

<?php
header('X-XRDS-Location: http://example.net/pureid.php?xrds=username');

This header can be included in any page that is already present at the identity URL, such as a blog.

The identity URL can also serve the XRDS document directly, but it cannot externally redirect to it, because the URL after redirection would then be considered the OpenID identifier.

Secure authentication

Passwords are stored in hashed form in the database, but are transmitted unencrypted while logging in. Connection-level security such as SSL should be used to protect them.

The optional $interface setting is an URL which is used for all interactions with the user. This could be the HTTPS version of $endpoint. For example

$interface = 'https://example.net/pureid.php';

File security

The best protection for the configuration file and SQLite database files is to put them outside the web root. If this is not possible, the webserver must be configured not to serve files from the SQLite database directory. With Apache, place a .htaccess file in that directory with the directive

Deny from all

Then check that the database file cannot be downloaded.