Sunday 21 October 2012

User Only authentication

I remember reading somewhere not too long ago - but I can't remember where! Sorry - about a suggestion for authentication that relied on browser sessions and the "Remember Me" idea to totally remove the need for passwords. The basic idea was that if you need to log in, you enter your email address into a box and the server will email you a specially crafted link. Following that link will then work as a one-time login to the site, but in such a way that it will keep you logged in until you press the Log Out button. This has the advantage that you only need to have access to your email to be able to log into the site.

I've been dwelling on this idea, and thought of some potential extensions to it to make life even easier for people. The first thought was to detect if the email was a Google Account, and if so then use Google Authentication - meaning to redirect through the Google Account Login process - to log you in. This has the advantage that if you are already logged into your Google account in the browser then you need do almost nothing to log into the website in question. The big problem with this idea is that, as best as I can work out, there is no way to detect if a given email address is a valid Google Account or not. I have, however, found a way to detect if a domain name is a valid Google Apps domain, and this can be coupled with the fact that the standard Google addresses are only from a very small set - gmail.com and googlemail.com are the only ones I believe.

The next step on this idea was to extend it to support more than just email addresses. It would be really good if you could just enter a twitter handle, or a facebook account name, or an OpenID address, or any of a whole set of potential identifiers from external authentication providers and then just do the correct thing. Of course, the big problem here is working out if an entered string is actually a valid account with a given provider, and if so then which one. The following I've worked out probably covers a fair few bases, but isn't totally reliable.

  • Google Account. Email address where the domain is either "gmail.com" or "googlemail.com"
  • Google Apps At My Domain. Make a request to https://www.google.com/accounts/o8/site-xrds?hd=. If you get a 400 back then it's not a valid Google Apps domain. Unfortunately this doesn't guarantee that you can authenticate the given email address with Google.
  • OpenID. These are always URLs, and you can make a request to the URL with an Accept header of "application/xrds+xml". This should give you a valid XRDS response.
  • Twitter. If the entered string starts with an "@" symbol, this might be a Twitter handle. It is possible to use the Twitter API to query a given screen name to see if it is a real Twitter account. Note that for this you need valid Twitter API credentials.
  • Facebook Accounts. It's possible to use the Facebook Graph API to determine if a given name is a valid Facebook account. Note that for this you need valid Facebook API credentials.
Once you've worked out that a given identifier is something we can handle, you can then do the appropriate magic to redirect the user through that providers authentication system to handle that part of things, and come back to your site with the fact that the user is now fully authenticated. All of the above also support getting some user details to fill out their profile if the credentials represent a new account and not an existing one.

There are a whole host of other providers that you can do similar things with too, but obviously the more providers you opt to support, the more difficult it becomes to know which provider a given identifier should go through. For example, I could opt to support Facebook AND Github accounts, but if the same identifier at Facebook and Github actually map onto two different people this causes big problems. If the only supported options are those listed above then the identifier is guaranteed to only map onto one of those providers - because the format for the identifiers are all different. Of course, one workaround here is to detect when the identifier maps onto multiple providers and prompt the user to select the provider they meant, but this makes the authentication process that little bit clunkier which is a real shame.

I'm going to try and build a proof of concept of the above ideas later on, to see how well it works in reality.

Edit: Turns out, there's one huge problem with this idea. And unfortunately it's a bit of a show stopper. OpenID is easy. Google Accounts in theory should be as easy, because they support OpenID, but actually they fall into the same problems as Facebook and Twitter - namely the fact that the APIs don't have any support for telling the authenticator which username we want to authenticate. This means that auto-detecting the authenticator based on the username is easy, but we'd end up redirecting the user to a login screen that wants them to enter those details again...

No comments:

Post a Comment