Setting up a single-user OpenID serverEdit

These are notes made while setting up my own single-user OpenID server. I wanted to set up my own server for the same reasons stated by Christopher Niemira, author of phpMyID, who writes:

I really don't like the idea of coupling a theoretically decentralized framework to one of a handfull of third party providers (and giving them my account credentials).

I chose to use phpMyID because it was a very simple implementation with no dependencies (not even a database).

Preparation

Based on information found here and here I proceeded to do the following:

Generate en MD5 hash of:

  • a username, the_username
  • realm, OpenID
  • password, the_password
echo -n "the_username:OpenID:the_password" | md5

Installation

I then exported a copy of the latest version of the relevant files from phpMyID:

cd path/to/web/directory
sudo svn export https://www.siege.org/svn/oss/phpMyID/trunk/MyID.php id.php
cd path/to/configuration/directory
sudo svn export https://www.siege.org/svn/oss/phpMyID/trunk/MyID.config.php id_config.php

Three things to note:

  • Use of sudo because I wasn't running as a user with write privileges
  • Renaming the files to id.php and id_config.php for aesthetic reasons
  • Storing the configuration file, id_config.php, outside of the web root

This last point is just basic security practice whenever I'm forced to use PHP: passwords and other sensitive configuration should always be stored outside of the webroot, just in case there is ever a problem with the Apache/PHP configuration that might cause the files to be served up as raw text rather than executed as a PHP script. In this case the risks are mitigated by the fact that the password is not stored in the configuration file (only a hash is stored) but it is basic security practice to adopt a multi-layered "onion" approach that implements multiple, separate barriers to guard against breaches. If an attacker were to access the configuration file brute-forcing a working password would be fairly easy because the user name wouldn't be hard to guess, the realm is publicly discoverable, and the hash isn't even generated using a salt.

Configuration file changes

22,23c22,24
<       'auth_username' =>      'test',
<       'auth_password' =>      '37fa04faebe5249023ed1f6cc867329b'
---
>       'auth_username' =>      'example_username',
>       'auth_password' =>      'example_hash',
>       'auth_realm'    =>      'OpenID'
38,40c39,41
< #     'nickname'              => 'Joe',
< #     'email'                 => 'joe@example.com',
< #     'fullname'              => 'Joe Example',
---
>       'nickname'              => 'Wincent',
>       'email'                 => 'example@example.com',
>       'fullname'              => 'Wincent Colaiuta',
44,46c45,47
< #     'country'               => 'US',
< #     'language'              => 'en',
< #     'timezone'              => 'America/New_York'
---
>       'country'               => 'ES',
>       'language'              => 'en',
>       'timezone'              => 'Europe/Madrid'

id.php changes

779c779
<               if (! @include('MyID.config.php'))
---
>               if (! @include('/full_path_to_conf_dir/id_config.php'))

Other set-up

The following HTML needed to be added to the page residing at my "identity" URL:

<link rel="openid.server" href="https://wincent.dev/id.php" />
<link rel="openid.delegate" href="https://wincent.dev/id.php" />
<meta http-equiv="X-XRDS-Location" content="https://wincent.dev/id.php" />

Results

To test the system I made my first post using OpenID-based authentication here. There are two problems with the result:

  1. The "from" line reads as http://wincent.dev/a/about/wincent/weblog/, which doesn't exactly make clear the identity of the poster; this is because it just redirects to my weblog at the other URL.
  2. The the user profile linked to from the comment doesn't include the extra information that I included in my configuration.

The second problem is probably a limitation of LiveJournal and there's not much that I can do about that. I decided to address the former problem by choosing a better URL for future identification. So I set up a simple page with the following content:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <title>example.com</title>
  <link rel="openid.server" href="https://wincent.dev/id.php">
  <link rel="openid.delegate" href="https://wincent.dev/id.php">
  <meta http-equiv="X-XRDS-Location" content="https://wincent.dev/id.php">
</head>
<body>
<ul>
  <li>Wincent Colaiuta's personal weblog: <a href="http://example.com/">example.com</a></li>
  <li>Mac OS X software: <a href="http://wincent.dev/">wincent.dev</a></li>
</ul>
</body>
</html>

From now on when I sign in using that URL the identity should be much more intelligible.