One of the biggest issues with OpenID is its usability. Many relying parties are currently faced with a difficult choice: how do you let the user know the provider they should be using? Users may be familiar with the brands of Facebook, Google, Yahoo, etc, but if your site doesn’t show it, then it may as well not exist. For the time being, at least, the OpenID brand is invisible (and in fact, sometimes is considered a negative).
As I see it, the fundamental problem we would like to solve is to figure out what are the most likely OpenID providers that the user would like to use? There are a few approaches to this:
- Show logos for the most popular providers. This is currently a common option, popularized by Janrain’s RPX and numerous other sites. This scales up to maybe 4-8 providers - beyond that, we get into what Chris Messina dubs the “OpenID Nascar”
- Show a dropdown of popular providers. This scales to maybe a few more, but starts to suffer from the value problem. What’s the first element of the dropdown? Do users understand what the “openid” moniker means that sits in front of it? (the answer: nope)
- Let the user type in a url. You can provide a simple textbox, or better yet, a typeahead, in which the user can enter the service provider. The problem is that without prompting, users don’t really understand the value or what to write - in fact, they will type just about anything in there. You can see what this looks like here.
The core problem is that we are relying entirely on the user to tell us what their provider is, but we can’t really ask them an intelligent question without explaining the value first. And the catch-22 is that the value provided relies sometimes on the provider! For instance, I may not know what OpenID is or internet identity or whatever, but I just want to log in okay?
A solution: detect the user’s provider
Okay, so let’s not just ask the user. Let’s ask the user’s browser, and let it tell us who their provider is. There are a few brainstormed techniques for doing this, none of which is particularly widespread at the moment:
- One idea that’s commonly suggested but not implemented is to use some strange browser history hacks to determine what sites the user has visited recently. If an OpenID provider appears in the list, then target the message to them. Fantastic!
While this would work with today’s technology, I think most sites have shied away from it because the information comes via an exploited bug rather than intentional, informed consent.
- We could build support into the OpenID spec for detecting the user’s current logged-in state. Relying parties could iterate through a whole bunch of possible providers, and if the user is currently logged in, they can show them a login screen. The performance would hardly be as bad as people think - requests can go in the background, in parallel, and you could theoretically query dozens or hundreds of providers within a few seconds (although I admit I haven’t tested it). See more discussion below.
- We could create a centralized authority or authorities for managing user OpenID provider preferences. People could set a single cookie with their preferred provider, and then every relying party can check that cookie via a cross-domain call. Some Google engineers have initiated some discussion of this based on a similar model used for advertising, but it suffers from a severe chicken-and-the-egg problem. I think that we first need to feel some pain from these other approaches first before everyone gets fed up and moves to a centralized model
OpenID needs a middle state
I think #2 is the best option of the three. OpenID already supports two types of requests- first, modal calls, with a mode of “checkid_setup”, tell the provider to ask the user to login. This is the standard mode that most people are familiar with, and much of the user experience discussion (including my previous post about the popup UI) has focused on it.
The second type of call is triggered with a mode of “checkid_immediate”, and it, well, always returns immediately. This mode is used by a relying party to re-authorize a user that has previously visited the site. When a provider receives an immediate request, it can send only one of two replies:
- Yes: Yes, the user is currently logged in, and they have previously authorized your website, so here’s their identifier. (mode is “id_res”)
- No: Nope, don’t know anything about them, you have to send them over to find out. (mode is “setup_needed”).
By contrast, Facebook Connect offers more functionality. If an application (relying party) queries the Facebook servers for a given user, it can return three states: returns three states:
- Yes, the user is logged into Facebook and they previously authorized your website.
- The user is logged into Facebook, but they haven’t authorized your site.
- No, we don’t know anything about this user.
There’s currently no way to communicate that middle state via the OpenID protocol. What I would like to see is an additional parameter that’s part of the “setup_needed” mode, which says in effect “the user is logged in, so if you present them with a dialog, it will be an easier experience than with other providers”.
Objection: what if a provider doesn’t want to?
Releasing logged-in state can be an optional feature. There should be a way to return logged-in state within the context of an OpenID transaction. Right now, there’s no standard way to do this, so providers that want to need to invent their own way to release that state.
Of course, the OpenID community has been fighting an uphill battle to even get the basic checkid_immediate call to work. Google, MyOpenID, and many others behave correctly, but even top providers like Myspace, Yahoo, and Microsoft always return a negative response to immediate requests - even when the user is logged in and authorized! We clearly still have a lot of work to do to make checkid_immediate a standard across all top providers.
Nonetheless, the spec should make it possible for providers who WANT to offer this additional state to do so. Just as some providers choose to offer checkid_immediate and others don’t, likewise we should allow those who want to the ability to return a more nuanced reply.
Objection: what if the user is logged into more than one provider?
So let’s say this becomes widespread. A user shows up to a relying party, and the background ping reveals that the user is logged into Facebook, Google, and Yahoo. Now what?
I think this would be a great problem to have. The relying party could present the user with choices if it wanted to, except confident in the fact that the user is familiar with all the choices. Or, a relying party could choose the provider that it has found gives it consistently better data and user experience. Or it could choose based on security preferences. The point is, the interface is still in the control of the relying party, but now the RP has strictly more information to make a better experience for its users.