Ever since I signed up on StackOverflow.com roughly a year ago, I’ve had an OpenID. On the whole, I think it’s a great concept, and I wish more sites would allow me to sign in with it.
However, a few things have been bothering me about it.
When I first signed up, I did a bit of research, and found out that you can use your own domain as your OpenID. You simply enter the following in a <head> of a HTML page you control:
<link rel="openid.server" href="http://myopenidprovider" />
<link rel="openid.delegate" href="http://myopenid-at-that-provider/" />
And the URI of that HTML page can now be used as your OpenID. It will forward authentication requests to the specified provider. This gave me a nice clean URI to use as my OpenID, and as a bonus, it meant that I could change my OpenID provider and keep my ID, just by editing this HTML.
Of course, I quickly found out there was a downside as well. When I created this blog, I placed it in http://jalf.dk/blog. I figured I could easily add a redirect from http://jalf.dk and so it wouldn’t matter in the long run.
When I tried adding this redirect, I realized that this of course would also redirect any OpenID requests. My OpenID provider would then see a login attempt from http://jalf.dk/blog instead, and all hell would break loose.
So I removed the redirect, and instead placed this message in http://jalf.dk/ along with the OpenID <link> tags:
Please go here for my blog. Sorry for the lack of a proper redirect.
Not very elegant, but it worked. OpenID requests were handled correctly, and readers of my blog could follow the link, or just bookmark /blog in the first place.
Today, a friend asked me why I didn’t have a redirect, and I explained the above problem. I didn’t think about it any further until half an hour ago, when I realized that Facebook can be tied to an OpenID account. As I said before, the more services I can log in to with my OpenID, the better, so I attempted to add my OpenID… And got a nasty error message telling me that my OpenID only supported version 1.1, and Facebook required 2.0.
Geez, I hadn’t even realized there were multiple versions.
So I went hunting for a solution. And it turned out to be pretty simple, and have the nice side effect of solving the redirection problem as well!
It turns out that the <link> tags embedded in HTML only work for OpenID 1.0 and 1.1. For 2.0, you have to provide a YADIS XML file.
Unfortunately, there seems to be very few examples online of what this file should look like. I did find a nice example of using a YADIS file for OpenID 1.0 here, which got me started. The Wikipedia article on YADIS held another example, but again only with OpenID 1.0. However, it also shows how to specify LID 2.0, so while I have no clue what LID is for, at least it gave a hint of how to support multiple versions.
Finally, diving into the specification for OpenID 2.0, I discovered the correct URI to specify as <Type> in the YADIS file: http://specs.openid.net/auth/2.0. Of course they just had to change the URI format between versions 1.1 and 2.0. Nothing is ever that easy.
But with this, the last piece fell into place. I created an openid.xml file looking like this:
< ?xml version="1.0" encoding="UTF-8"?>
<xrds:XRDS xmlns:xrds="xri://$xrds" xmlns="xri://$xrd*($v*2.0)"
xmlns:openid="http://openid.net/xmlns/1.0">
<XRD>
<Service priority="50">
<Type>http://specs.openid.net/auth/2.0/signon</Type>
<URI>http://myopenidprovider</URI>
<openid:Delegate>http://myopenid-at-that-provider/</openid:Delegate>
</Service>
<Service priority="20">
<Type>http://openid.net/signon/1.1</Type>
<URI>http://myopenidprovider</URI>
<openid:Delegate>http://myopenid-at-that-provider/</openid:Delegate>
</Service>
<Service priority="10">
<Type>http://openid.net/signon/1.0</Type>
<URI>http://myopenidprovider</URI>
<openid:Delegate>http://myopenid-at-that-provider/</openid:Delegate>
</Service>
</XRD>
</xrds:XRDS>
and using the PHP snippet from paulisageek,
< ?php
if (strpos($_SERVER['HTTP_ACCEPT'], "application/xrds+xml") !== FALSE) {
header("Content-Type: application/xrds+xml");
echo file_get_contents("openid.xml");
}
else {
header("Location: http://jalf.dk/blog");
}
?>
I now have:
- The same nice, short, easy-to-remember OpenID URI I always had
- My blog accessible form
http://jalf.dk - My Facebook account linked to my OpenID
- Support for OpenID version 2.0
All in all, I’m happy. And now that I’ve documented the process, perhaps the next person who runs into this problem may be a bit happier too.




