Running my own identity server

Context and motivation

I have been an happy user of Janrain‘s OpenId provider, myOpenId since May 2007 and didn’t feel any urgency to change until their announcement that the service will close on February 1, 2014:

Janrain, Inc. | 519 SW 3rd Ave, Suite 600, Portland OR 97204 | 888.563.3082 | janrain.com <http://www.janrain.com>
Hello,

I wanted to reach out personally to let you know that we have made the decision to end of life the myOpenID <https://www.myopenid.com/> service. myOpenID will be turned off on February 1, 2014.

In 2006 Janrain created myOpenID to fulfill our vision to make registration and login easier on the web for people. Since that time, social networks and email providers such as Facebook, Google, Twitter, LinkedIn and Yahoo! have embraced open identity standards. And now, billions of people who have created accounts with these services can use their identities to easily register and login to sites across the web in the way myOpenID was intended.

By 2009 it had become obvious that the vast majority of consumers would prefer to utilize an existing identity from a recognized provider rather than create their own myOpenID account. As a result, our business focus changed to address this desire, and we introduced social login technology. While the technology is slightly different from where we were in 2006, I’m confident that we are still delivering on our initial promise – that people should take control of their online identity and are empowered to carry those identities with them as they navigate the web.

For those of you who still actively use myOpenID, I can understand your disappointment to hear this news and apologize if this causes you any inconvenience. To reduce this inconvenience, we are delaying the end of life of the service until February 1, 2014 to give you time to begin using other identities on those sites where you use myOpenID today.

Speaking on behalf of Janrain, I truly appreciate your past support of myOpenID.

Sincerely,
Larry

Larry Drebes, CEO, Janrain, Inc. <http://bit.ly/cKKudR>

I am running a number of low profile web sites such as owark.org, xformsunit.org or even this blog for which OpenID makes sense not only because it’s convenient to log into these sites with a single identity (and password) but also because I haven’t taken the pain to protect them with SSL and that https authentication on an identity server is safer than http authentication on these sites.

On the other hand I do not trust « recognized providers » such as « Facebook, Google, Twitter, LinkedIn and Yahoo! » and certainly not want them to handle my identity.

The only sensible alternative appeared to be to run my own identity server, but which one?

My own identity server

The OpenID wiki gives a list of identity servers but a lot of these seem to be more or less abandoned, some of the links even returning 404 errors and I have chosen to install SimpleID which is enough for my needs and is still being developed.

Its installation, following its Getting Started guide is straightforward and I soon had an identity server for my identity « http://eric.van-der-vlist.com/« . The next step has been to update the links that delegate the identity on this page to point to my new identity server instead of myOpenID:

  <link rel="openid.server" href="https://eudyptes.dyomedea.com/openid/" />
  <link rel="openid.delegate" href="http://eric.van-der-vlist.com/" />
  <link rel="openid2.local_id" href="http://eric.van-der-vlist.com/" />
  <link rel="openid2.provider" href="https://eudyptes.dyomedea.com/openid/" />

Working around a mod_gnutls bug on localhost

At that stage I was expecting to be able to be able to log into my websites using OpenID and that did work for owark.org and xformsunit.org but not from this blog!

Trying to log into this blog logged a rather cryptic message into Apache’s error log:

CURL error (35): error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol, referer: https://blog.eric.van-der-vlist.com/wp-admin/users.php?page=your_openids

The same error was reported when trying to access the identity server using cURL and even OpenSSL:

vdv@corp:~$ openssl s_client -debug -connect eudyptes.dyomedea.com:443
CONNECTED(00000003)
write to 0x6aa5a0 [0x6aa620] (226 bytes => 226 (0xE2))
0000 - 16 03 01 00 dd 01 00 00-d9 03 02 52 2b 09 1e 75   ...........R+..u
0010 - 8b 8a 35 91 0e ba 6a 08-56 c6 34 a9 d8 78 d3 e8   ..5...j.V.4..x..
0020 - 70 cc 92 36 60 d2 41 32-f1 e8 0f 00 00 66 c0 14   p..6`.A2.....f..
0030 - c0 0a c0 22 c0 21 00 39-00 38 00 88 00 87 c0 0f   ...".!.9.8......
0040 - c0 05 00 35 00 84 c0 12-c0 08 c0 1c c0 1b 00 16   ...5............
0050 - 00 13 c0 0d c0 03 00 0a-c0 13 c0 09 c0 1f c0 1e   ................
0060 - 00 33 00 32 00 9a 00 99-00 45 00 44 c0 0e c0 04   .3.2.....E.D....
0070 - 00 2f 00 96 00 41 c0 11-c0 07 c0 0c c0 02 00 05   ./...A..........
0080 - 00 04 00 15 00 12 00 09-00 14 00 11 00 08 00 06   ................
0090 - 00 03 00 ff 02 01 00 00-49 00 0b 00 04 03 00 01   ........I.......
00a0 - 02 00 0a 00 34 00 32 00-0e 00 0d 00 19 00 0b 00   ....4.2.........
00b0 - 0c 00 18 00 09 00 0a 00-16 00 17 00 08 00 06 00   ................
00c0 - 07 00 14 00 15 00 04 00-05 00 12 00 13 00 01 00   ................
00d0 - 02 00 03 00 0f 00 10 00-11 00 23 00 00 00 0f 00   ..........#.....
00e0 - 01 01                                             ..
read from 0x6aa5a0 [0x6afb80] (7 bytes => 7 (0x7))
0000 - 3c 21 44 4f 43 54 59                              <!DOCTY
140708692399776:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol:s23_clnt.c:749:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 226 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---

Of course, the same commands did work perfectly on the servers hosting owark.org and xformsunit.org and I was puzzled because these two servers are running the same versions of the same software with very similar configurations.

The main difference is that my blog runs on the same server than the identity server. Looking closely at the result of the openssl command I noticed that the server was returning plain text instead where encrypted content was expected. Knowing that the server is using mod_gnutls to serve its https content (this is needed to support wildcards in SSL certificates), I was soon able to find a bug, reported in September 2011 which has been fixed but never ported into Debian or Ubuntu packages: mod_gnutls doesn’t encrypt the traffic when the IP source and destination addresses are identical.

Since the fix is not easily available I had to find a workaround… How could I trick the server giving it a source address that would be different from the destination address?

With my current configuration, both addresses were 95.142.167.137, the address of eudyptes.dyomedea.com. What if one of these addresses could become 127.0.0.1?

These addresses can easily become 127.0.0.1, to do so you just need to say so in /etc/hosts:

127.0.0.1       localhost eudyptes.dyomedea.com

Of course at that stage, both addresses are equal to 127.0.0.1 instead of 95.142.167.137. They are still equal and that doesn’t fix anything.

The trick is then to update the Apache configuration so that its doesn’t listen on 127.0.0.1:443 anymore:

    Listen 95.142.167.137:443

So that we can redirect 127.0.0.1:443 on 95.142.167.137:443. To do so we can use iptables but we don’t need the full power of this tool and may prefer the simplicity of a command such as redir:

sudo redir --laddr=127.0.0.1 --lport=443 --caddr=95.142.167.137 --cport=443 --transproxy

This redirection changes the destination address to 95.142.167.137 without updating the source address which remains 127.0.0.1. The addresses being different mod_gnutls does encrypt the traffic and our identity server becomes available on the local machine.

Other tweaks

Note that if you’re using WordPress and its OpenID plugin you may have troubles to get OpenID login working with the excellent Better WP Security plugin and will have to disable « Hide Backend » and « Prevent long URL strings » options.