First I obtained an OpenID account with www.myopenid.com. I actually have several other accounts with other OpenID Providers, such as pip.verisignlabs.com and yahoo.com because some relying parties allow only white-listed Providers, and some services offer me an OpenID whether I use it or not.
But to avoid an identity crisis of appearing all over the web as http://andrew.arnott.myopenid.com, http://andrewarnott.signon.com, http://aarnott.pip.verisignlabs.com, etc., I wanted to tie all these logins together under one identifier that I would always use, so people would be able to recognize the same person is behind all these identifiers. Using an XRDS document, I can do this. I created this document to describe all my OpenID Provider accounts:
<%@ Page ContentType="application/xrds+xml" %><?xml version="1.0" encoding="UTF-8"?> <xrds:XRDS xmlns:xrds="xri://$xrds" xmlns:openid="http://openid.net/xmlns/1.0" xmlns="xri://$xrd*($v*2.0)"> <XRD> <Service priority="10"> <Type>http://specs.openid.net/auth/2.0/signon</Type> <Type>http://openid.net/signon/1.0</Type> <Type>http://openid.net/sreg/1.0</Type> <Type>http://openid.net/extensions/sreg/1.1</Type> <Type>http://specs.openid.net/extensions/pape/1.0</Type> <URI>https://www.myopenid.com/server</URI> <LocalID>http://andrew.arnott.myopenid.com</LocalID> <openid:Delegate>http://andrew.arnott.myopenid.com</openid:Delegate> </Service> <Service priority="20"> <Type>http://specs.openid.net/auth/2.0/signon</Type> <Type>http://specs.openid.net/extensions/pape/1.0</Type> <URI>https://open.login.yahooapis.com/openid/op/auth</URI> <LocalID>https://me.yahoo.com/a/cJASAdp4x5Rx6CU9olKi7rMkG1TX_7Yl1kQ-</LocalID> </Service> <Service priority="30"> <Type>http://specs.openid.net/auth/2.0/signon</Type> <Type>http://openid.net/signon/1.0</Type> <URI>https://www.signon.com/partner/openid</URI> <LocalID>https://andrewarnott.signon.com</LocalID> <openid:Delegate>https://andrewarnott.signon.com</openid:Delegate> </Service> <Service priority="40"> <Type>http://specs.openid.net/auth/2.0/signon</Type> <Type>http://openid.net/signon/1.0</Type> <URI>https://pip.verisignlabs.com/server</URI> <LocalID>https://aarnott.pip.verisignlabs.com</LocalID> <openid:Delegate>https://aarnott.pip.verisignlabs.com</openid:Delegate> </Service> </XRD> </xrds:XRDS>
There is a little ASP.NET tag at the beginning to make sure the server sends down the proper Content-Type HTTP header with the document so Relying Party web sites know what they're looking at. I was also careful to include the right <Type> tags in each service, as some services support just OpenID 1.x, some just 2.0, and some both. Some support extensions as well so I included those. Finally, each service has a priority attribute on it that allows the RP to sort the list based on my preferences and then choose the first Provider that fulfills the RP's requirements.
This XRDS document, at a URL, could serve as my OpenID URL itself. But http://someserver/somexrds.aspx would be an ugly OpenID URL. So I needed to refer to this document from a URL that was easier on the eyes and the fingers.
First I had to choose an Identifier that I would always use. I did not want to use any Identifier that is specific to an individual OpenID Provider for two reasons:
- I might want to stop using that Provider at some point in the future.
- Most Providers do not let me add additional services to the XRDS document that they host for me.
A common choice is a blog URL. I had already been using this snippet on my blog to host an OpenID identity:
<link rel="openid.server" href="https://www.myopenid.com/server"/>
<link rel="openid.delegate" href="http://andrew.arnott.myopenid.com"/>
<link rel="openid2.provider" href="https://www.myopenid.com/server"/> <link rel="openid2.localid" href="http://andrew.arnott.myopenid.com"/>
This link style has the limitation of only allowing one of my Providers to be listed. But some RPs only support this syntax and cannot read XRDS documents, so while leaving this snippet here, above it I inserted the following snippet (within my Blogger-hosted blog's HEAD section):
<meta content='http://nerdbank.net/openid_xrds.aspx' http-equiv='X-XRDS-Location'/>
Great. Now http://blog.nerdbank.net is my omni-identity. I can log into any OpenID relying party web site, and (assuming that site uses a decent implementation of OpenID) the RP will let me log in even if my first choice Provider isn't strong enough by looking down the list until it finds one that is. If I don't have any that are good enough, I can just create an account at one more Provider and add it to my list and I don't have to worry about changing my OpenID URL that I use everywhere.
For example, Microsoft HealthVault has a whitelist of only two allowed Providers (including Verisign) that their visitors may log in with. No problem. I just log in as http://blog.nerdbank.net and the RP should (HealthVault actually doesn't support all this yet) find the Verisign service in my XRDS document and automatically direct me to Verisign for authentication, even though it's nearly last on my preferred list of Providers.
To summarize: I now have http://blog.nerdbank.net as my OpenID that I can use to log into any OpenID 1.x or 2.0 relying party web site (provided it has a decent implementation), regardless of what Providers each site may require I use.
In my next post, I'll discuss how to use XRI i-names to further secure your identity.