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...

Monday 15 October 2012

REST authentication concerns

I've just read a blog post suggesting ways to do user authentication on a REST based service, and - as is far too common - they got it totally wrong. They detailed a means to generate hashes based on the message and shared secrets that only that user would know.

REST is fundamentally based on a few things. One of these is to leverage the HTTP protocol wherever possible. You already see this in the use of HTTP verbs for actions, URLs to refer to resources, status codes for error handling, amongst other things. Following this through, logically the sensible way to do user authentication is to do HTTP auth. It's clearly defined by the HTTP specifications - RFC2617 is a decent place to start here - and gives exactly what is wanted. It also gives a number of different ways to manage how user credentials are sent to the server, and you get to define your own if you really need to. What more could you ask for?

The obvious problem with it is that the standard http auth mechanisms - basic and digest - can be vulnerable to man in the middle attacks. But there's an answer to that too. You should never send anything sensitive - like authentication headers - over plain http. Use https instead. It's so simple to set up these days, and certificates can be self generated or bought for really not very much, so there's no excuse not to!

Thursday 4 October 2012

New Features for your favourite C++ Compiler

Herb Sutter has a post up on Sutters Mill asking what people would like to see added to their favourite C++ Compiler. Unsurprisingly, Conformance has so far come out at the top. This is literally nothing more than adding all of the features in the C++ Specification (C++11 mostly, but I'm sure that there are compilers out there that have missing features from older versions) that haven't been implemented yet. What I found surprising was that Performance is second place.

On modern hardware, unless you are doing realtime or embedded programming, do you really need your compiler to be able to make your code run that much faster? And by "that much faster", the entry for Performance I was to increase the speed by 5%. That's not a lot, and if you are writing native code to run on modern hardware, and that 5% speed improvement is that important then I have to wonder what you are doing.

I honestly expected that Safety would come out higher than Performance. Safety in this sense is split into two cases - STL Safety and Language Safety. STL Safety is making it so that actions on STL components are thread- and bounds-safe with minimal overhead,and Language Safety is the same but for non STL components. It's true that a lot of this is considered unnecessary because you should know what your program is doing, and it shouldn't be doing any unsafe actions, but we all know that this isn't always the case, and having compiler guards that catch these things with minimal overhead would make a lot of our programs a lot safer to run. I personally think this is a lot more important than making the programs run that little bit faster.

For the record, my last vote went to adding some more Reflection capabilities into the language. Certainly not to the level of languages like Groovy or Ruby, where you can totally re-write the interfaces of objects at runtime (That scares me), but being able to introspect types at runtime, and instantiate them by name, and things like that can be very useful on occasion and right now just can't be done in C++ without a lot of nasty hacks.