OpenID: Redirects and Delegation

The Introduction

I’m a big fan of OpenID. I like the fact that my online (public) identity is associated with a URL that I own. This affords quite a few benefits, such as associating my public profile at various networks with one another. Even better, OpenID supports the delegation of identifiers to OpenID Providers. This allows the owner of a domain to use the domain as an OpenID without operating his own OpenID server. He simply delegates the provider responsibilities to an existing provider by adding some HTML link references at the top of his OpenID URL. But before I get too far ahead of myself, a bit of history.

The History

The Global Name Registry was delegated the .name top-level domain by ICANN in 2001. [Wikipedia] The intention was to set aside a specific top-level domain for individuals to register as their own domain. These domains may be registered on the second level (john.name) and the third level (john.doe.name). Generally, the second level domains are shared among the registrants of the third-level. (Aside: I find it rather surprising that the assortment of ancestry sites don’t take advantage of this for linking in family trees) In 2007 the GNR spun-off a small start-up formed as a partnership with JanRain‘s OpenID provider, myOpenID. This partnership created FreeYourID.com. The goal of FreeYourID was to make it dead simple for users to both register their own .name domain and use it as an OpenID. FreeYourID provided a couple great features. The domain registration was transparent to the end user, making it very friendly to non-techies. A .name email address was created (john@doe.name). FreeYourID provided a few URL forwarding options for those with existing domains. They had a decent default landing page that aggregated various social network profiles (YouTube, Flickr, Blogs). They even supported microformats with XFN! And via the partnership with myOpenID, the .name domain was automatically setup as an OpenID.

The Situation

So in 2007 I registered jason.karns.name from FreeYourID.com. A myOpenID account was created behind the scenes which handled the OpenID login. So as an end user I would attempt OpenID log-in at a relying party, which would navigate to jason.karns.name and encounter the OpenID delegation snippets. This would foward over to myOpenID (tied to the shim account) where I would authenticate and be redirected back to the original service having been authenticated as jason.karns.name. I used this service for 2 years as OpenID was beginning to gather steam. I used jason.karns.name as my primary web address (which was forwarded to other sites). I collected a few social network links on FreeYourID’s social network page (which provided a great resource for XFN crawlers). But most importantly, I used my OpenID as my primary (in some cases, only) authentication method at quite a few online services.

The Problem

At the beginning of 2009, the .name domain was transferred to VeriSign. This spelled the beginning of the end for FreeYourID. Toward the end of the year, FreeYourID announced it was shutting down and would be transferring all services over to DomainDiscount24. Prior to the transfer, I purchased jasonkarns.com. Once my .name was transferred, I setup an HTTP 301 redirect from jason.karns.name to jasonkarns.com. The landing page of jasonkarns.com contained the same OpenID delegation snippets as jason.karns.name so I assumed everything would continue to work. I was wrong. This setup prevented me from logging in at every service that used OpenID.

The Discovery

Through some digging and a bit of guidance by this post (thanks Will), I discovered that an OpenID relying part must follow all redirects and the final destination URL is used as the OpenID Identifier rather than the original URL. So in my case, I would attempt to login with jason.karns.name which redirected to jasonkarns.com, which was then delegated to myOpenID. I would authenticate normally at myOpenID because the delegation snippets specify which account to use at the provider. However, when redirected back to the relying party, my authentication token reported my ID as jasonkarns.com. As there was no existing account registered for jasonkarns.com, most relying parties would initiate their ‘new user’ flow. Others just error-ed out.

The Fix

So now I realize what the root problem is, but I’m not sure how to fix it. I definitely have to get my OpenID working again so I must serve the OpenID delegation code from jason.karns.name directly. However, I also want to continue using jasonkarns.com as the primary online destination for people looking for me.

  1. Configure DomainDirect24 to stop the HTTP 301 redirect to jasonkarns.com
  2. Create a landing page for jason.karns.name which contains the OpenID delegation code
  3. Use the old-school meta-refresh to handle the redirect from jason.karns.name to jasonkarns.com. OpenID Relying Parties won’t follow the meta-refresh because they are only interested in the delegation code.
  4. Setup a frameset to load jasonkarns.com from within jason.karns.name. This is only for user-agents that don’t or won’t follow the the meta-refresh. This way end users still end up with the same content.

The Result


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
 <head>
 <title>jason.karns.name</title>
 <meta http-equiv='Content-type' content='text/html; charset=utf-8' />
 <!-- OpenID server and delegate -->
 <link rel="openid.server openid2.provider" href="http://www.myopenid.com/server" />
 <link rel="openid.delegate openid2.local_id" href="http://jason.karns.name" />
 <meta http-equiv="X-XRDS-Location" content="http://www.myopenid.com/xrds?username=jason.karns.name" />
 <!--Redirect has been requested -->
 <meta http-equiv='refresh' content='0;url=http://jasonkarns.com' />
 </head>
 <!-- Frame Redirection for human content readers -->
 <frameset rows='100%,*' style='border:0;'>
 <frame src='http://jasonkarns.com' frameborder='0' />
 <frame frameborder='0' noresize='noresize' />
 </frameset>
</html>

The Future

While this isn’t the optimal solution, it works for now. I rather like the idea of potentially having 2 separate OpenIDs (though they are both delegated to the same myOpenID account). However, I don’t like the meta-refresh redirect. At one point there was a discussion going on for the OpenID spec around giving 303 (See Other) redirects special behavior—as oppposed to 301 (Moved Permanently), 302 (Found) and 307 (Temporary Redirect). Although at this point, I don’t hold much hope. My only other choice of action is to follow Will Norris’ method and use server-side HTTP Request sniffing and respond accordingly (OpenID delegation for suspected Relying Parties, 301 Redirect for everyone else).

One thought on “OpenID: Redirects and Delegation”

  1. Hey,

    Thanks for sharing this solution.
    It was very useful.

    Really, the meta-refresh is not the best-looking solution,
    but it does the trick in this redirect-complicated problem.

    Regards!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: