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: http://eric.van-der-vlist.com/blog/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.

Share and Enjoy:
  • Identi.ca
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Twitter
  • Add to favorites

Notes de migration de Gallery 2 vers WordPress et NextGEN Gallery

Quelques notes rapides prises lors de la migration de mes albums Gallery 2 vers le plugin WordPress NextGEN Gallery

Attention : les manipulations de bases de données décrites ici sont dangereuses et il n’y a aucune garantie qu’elles fonctionnent pour vous!

La première différence est terminologique :

  • Gallery gère une “galerie” qui est la racine de votre collection de photos et est composée d’albums pouvant être imbriqués les uns dans les autres (les albums sont composés de photos et d’albums).
  • NextGEN Gallery gère des “galeries” photos qui sont des ensembles de photos ne pouvant pas être imbriquées les uns dans les autres mais peuvant être groupées dans des “albums” qui peuvent, eux, être imbriqués les uns dans les autres (les galeries sont uniquement composées de photos et les albums sont composés de galeries et d’albums).

Cette différence se retrouve au niveau de la structure des répertoires, puisque les albums de Gallery forment physiquement une structure arborescence sur le système de fichier alors que les galeries de NextGEN Gallery sont toutes aux même niveau et que ses albums ne sont pas matérialisés sur le système de fichier (ils sont virtuels et n’existent que dans la base de données).

Mes albums Gallery avaient tous, c’est une chance, des noms uniques. J’ai donc simplement “aplati” la structure de fichiers après transfert dans wp-content/gallery et utilisé l’interface d’administration de WordPress pour créer les galeries à partir des répertoires que je venais de transférer.

Le nombre d’albums étant limité, je n’ai pas cherché à migrer leur définition et les ai également recréé manuellement dans l’interface d’administration.

Je voulais par contre éviter de perdre les métadonnées associées aux photos et c’est à ce niveau qu’il m’a fallu faire preuve d’un peu de “geekerie”!

J’ai commencé par examiner la base de données Gallery 2 (qui dans mon cas était gérée par MySQL) pour exporter ces métadonnées en XML :

vdv@dedibox4:/var/lib/wordpress_vdv/wp-content/gallery$ mysql -uroot -pXXXX --default-character-set=utf8 -X gallery2_vdv > /tmp/images.xml <<EOF
select 
	e.g_id,
	i.g_description,
	i.g_keywords,
	i.g_summary,
	i.g_title,
	f.g_pathComponent,
	fp.g_pathComponent,
	iam.g_orderWeight
from 
	g2_Entity e,
	g2_Item i, 
	g2_FileSystemEntity f,
	g2_ChildEntity ce,
	g2_FileSystemEntity fp,
	g2_ItemAttributesMap iam
where 
	e.g_entityType = "GalleryPhotoItem"
	and e.g_id = i.g_id 
	and e.g_id = f.g_id
	and e.g_id = ce.g_id
	and e.g_id = iam.g_itemId
	and fp.g_id = ce.g_parentId
order by fp.g_pathComponent,  iam.g_orderWeight;
EOF

A noter :

  • L’option “-X” pour formatter les données en XML
  • L’option “–default-character-set=utf8” indispensable dans mon cas pour éviter que MySQL n’insère des caractères ISO-8859-1 dans un document XML sans déclaration d’encodage!

Le document XML obtenu est de la forme :

<?xml version="1.0"?>

<resultset statement="select 
    e.g_id,
    i.g_description,
    i.g_keywords,
    i.g_summary,
    i.g_title,
    f.g_pathComponent,
    fp.g_pathComponent,
    iam.g_orderWeight
    from 
    g2_Entity e,
    g2_Item i, 
    g2_FileSystemEntity f,
    g2_ChildEntity ce,
    g2_FileSystemEntity fp,
    g2_ItemAttributesMap iam
    where 
    e.g_entityType = &quot;GalleryPhotoItem&quot;
    and e.g_id = i.g_id 
    and e.g_id = f.g_id
    and e.g_id = ce.g_id
    and e.g_id = iam.g_itemId
    and fp.g_id = ce.g_parentId
    order by fp.g_pathComponent,  iam.g_orderWeight" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <row>
        <field name="g_id">22909</field>
        <field name="g_description" xsi:nil="true" />
        <field name="g_keywords" xsi:nil="true" />
        <field name="g_summary" xsi:nil="true" />
        <field name="g_title">dsc00001</field>
        <field name="g_pathComponent">aaa.jpg</field>
        <field name="g_pathComponent">011120-Forum-XML-2001</field>
        <field name="g_orderWeight">1000</field>
    </row>
    
    <row>
        <field name="g_id">22913</field>
        <field name="g_description" xsi:nil="true" />
        <field name="g_keywords" xsi:nil="true" />
        <field name="g_summary" xsi:nil="true" />
        <field name="g_title">dsc00002</field>
        <field name="g_pathComponent">aab.jpg</field>
        <field name="g_pathComponent">011120-Forum-XML-2001</field>
        <field name="g_orderWeight">2000</field>
    </row>
    
    ...
    
</resultset>

A partir de ce document XML, j’ai ensuite écrit une transformation XSLT 2.0 pour générer les instructions SQL insérant les données correspondantes dans la base de données WordPress / NextGEN Gallery.

Pour cela, il faut créer les tags en insérant des lignes dans les tables wp_terms et wp_term_taxonomy :

insert into wp_terms (name, slug) values ("albatros d'amsterdam", "albatros d'amsterdam");
insert into wp_term_taxonomy (term_id, taxonomy, parent, count) select term_id, 'ngg_tag', 0, 0 from wp_terms where name = "albatros d'amsterdam";                  

Associer les tags aux photos et incrémenter les compteurs adéquats :

insert into wp_term_relationships (object_id, term_taxonomy_id, term_order) 
    select pid, term_taxonomy_id, 1
        from 
            wp_ngg_gallery g,
            wp_ngg_pictures p,
            wp_terms t,
            wp_term_taxonomy taxo
        where
        	p.galleryid = g.gid
        	and t.term_id = taxo.term_id
        	and g.title = "amsterdam-vrac"
        	and p.filename = "crop0011.jpg"
        	and t.name="albatros d'amsterdam";
update wp_terms t, wp_term_taxonomy taxo set count = count + 1 where t.term_id = taxo.term_id and t.name="albatros d'amsterdam";               

Et enfin, mettre à jour les photos elles mêmes :

update
	wp_ngg_gallery g,
	wp_ngg_pictures p
set
	p.image_slug = "dsc00001",
	p.description = "dsc00001",
	p.alttext = "dsc00001",
	p.sortorder = 1
where
	p.galleryid = g.gid
	and g.title = "011120-Forum-XML-2001"
	and p.filename = "aaa.jpg";

A noter que je me suis appuyé, là aussi, sur le fait que mes galeries ont des noms uniques et que l’on peut donc identifier les photos à partir de leur nom de fichier et du nom de leur galerie.

La transformation utilise bien entendu le template nommé décrit dans mon billet précédent.

Vous pouvez la télécharger si vous voulez y jeter un coup d’œil.

Une fois la migration achevée, il faut encore veiller à gérer les redirections (cool uris don’t change…), ce que j’ai fait ç grand coups d’expressions régulières :

RedirectMatch	301	^/gallery/				http://eric.van-der-vlist.com/blog/gallery/?
RedirectMatch	301	^/gallery2/v(/[^/]*)*(/[^/]*/[^/]*\.(jpg|JPG|png))	http://eric.van-der-vlist.com/blog/wp-content/gallery$2?
RedirectMatch	301	^/gallery2/v/(.*)/(slideshow\.html)	http://eric.van-der-vlist.com/blog/gallery/$1/?
RedirectMatch	301	^/gallery2/v/(.*)			http://eric.van-der-vlist.com/blog/gallery/$1?
RedirectMatch	301	^/gallery2/				http://eric.van-der-vlist.com/blog/gallery/?
Share and Enjoy:
  • Identi.ca
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Twitter
  • Add to favorites

Coup de neuf pour mon blog

Mon blog était hébergé sur un vieux serveur qui commence à donner des signes de faiblesses et son déménagement sur un serveur plus récent a été l’occasion de lui donner un petit coup de neuf…

Mises à jour de la version de WordPress et de ses plugins bien entendu, mais aussi changement de thème : le thème dkert3 que j’utilisais jusqu’à présent s’est subitement mis à générer une erreur PHP après l’upgrade et en activant Twenty ten (le nouveau thème par défaut de WordPress) pour examiner ce qui se passait j’ai trouvé qu’il convenait bien à ce blog.

Le plus gros changement est sans doute l’intégration de mon ancien album photo au blog.

Pour le moment, cette intégration est faite “à périmètre constant” et reproduit l’ancien album mais j’essayerai de trouver le temps de l’enrichir et de l’améliorer!

C’est album photo était auparavant géré par Gallery, un logiciel de gestion d’albums photos que j’utilisais depuis sa première version.

Pourquoi l’abandonner?

Le positionnement de Gallery devient un peu délicat : c’est un logiciel de gestion d’albums photos destiné à publier des photos sur le web et à les partager des photos avec ses amis ou sa famille sans être un logiciel de gestion de photos ou un DAM.

J’apprécie beaucoup le logiciel Gallery, mais il me semble qu’il est pris en tenaille entre les extensions permettant de gérer des albums photos directement dans les blogs et les DAMs qui permettent également de publier des photos sur internet.

Ma décision d’intégrer l’album photos a finalement été motivée par deux raisons :

  • le souhait de pouvoir intégrer plus facilement les photos de l’album au blog,
  • la charge de travail lié au maintient de deux logiciels différents pour le blog et pour l’album photo.

Avant de prendre cette décision, j’ai migré mon ancien album photo sous la dernière version de Gallery (Gallery 3) et ai testé les plugins heiv Gallery3 et  Gallery3 Picker qui permettent d’intégrer respectivement des albums et des photos de Gallery3 dans WordPress. Le résultat était satisfaisant mais il m’a semblé moins convainquant que le plugin de gestion de photos NextGen Gallery que j’utilise déjà sur le site du Retour à la Terre.

Outre ce plugin, j’ai également installé :

  • Broken Link Checker qui vérifie les liens inséré dans le blog. J’ai du travail à faire à ce niveau : le plugin a détecté 72 liens “cassés’!
  • OpenID qui me permet, ainsi qu’à mes visiteurs de m’identifier en utilisant un OpenID.
  • Une version modifiée de Comment Form Notes qui affiche un message pour inciter mes visiteurs à utiliser OpenID pour poster leurs commentaires (ils évitent ainsi la phase de “modération”).
  • pageMash, bien utile pour gérer l’arborescence des pages du blog.
  • Raven’s Antispam dont j’espère qu’il facilitera la tâche de gestion des commentaires sur le site. Dites moi s’il bloque intempestivement vos commentaires!
  • Redirection qui permet de garder des URLs cools (qui ne changent pas) et d’analyser les erreurs 404.
  • Relevanssi qui améliore les fonctions de recherche.
  • Shutter Reloaded qui gère l’affichage des photos de manière spectaculaire.
  • XRDS-Simple nécessaire au plugin OpenID.

Un grand merci aux développeurs de WordPress et de ces plugins!

L’écosystème WordPress continue de m’impressionner par sa richesse. C’est une des raisons pour lesquelles j’ai adopté WordPress mais cette richesse comporte aussi des risques : lorsque l’on dépend de 10 plugins et d’un thème pour gérer un site, les risques que quelque chose ne se passe pas bien quand on met à jour la version du moteur WordPress ne sont pas négligeables et on a tendance à croiser les doigts avant chaque mise à jour!

Share and Enjoy:
  • Identi.ca
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Twitter
  • Add to favorites

Adios Syncato

It’s been fun to use Syncato, but the lack of any kind of efficient anti spam is really overwhelming and I had to switch to something else to reopen the comments that I had to close with Syncato.

I am giving a try to WordPress which is in a way the complete opposite of Syncato: I don’t like that much its technical foundation (I had a look at its implementation of XML features and I’ll come back on that if time permits), but it is so much more user friendly that it’s difficult to resist… After all, I may be a XML Geek, I am also a user!

XSLT has been my friend again for this migration (the XML import that has been used to initialize the WordPress database and the rewrite rules have been generated with XSLT). As a result, all the posts, comments and feeds are available through the same URIs and the side effects should be minimized for the readers of this blog.

Farewell Syncato, I’ll miss your XML abilities!

Share and Enjoy:
  • Identi.ca
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Twitter
  • Add to favorites