This post/article was written by Chris Shiflett and myself a while ago. Both of us forgot about it until recently. I decided, as I don't have too much content on my blog, to post it here with Chris' consent.
We are all connected, and with recent trends in social networking and mashups, our personal identities are becoming more distributed than ever before. Because a chain is only as strong as its weakest link, this trend can have dangerous consequences. Instead of doing everything they can to help us protect our identities, some developers are utilizing a new technique that has been dubbed the password anti-pattern. This article explains the password anti-pattern and provides a brief introduction to OAuth, a possible solution.
Imagine yourself as a CEO of a company, and instead of keeping all your important business contacts on your cell phone or computer, you keep it all in a five dollar address book from Staples. You like things old school, those crazy computers just make things more complicated. Last night you brought your address book home and forgot to bring it with you to work today. You decide that you are too busy to run back home for it and call your assistant into the office. You hand over a set of spare keys to your house to your assistant, who, by the way isn't too fond of you after having been told he makes horrible coffee. You tell him to grab your address book from your home office, and to come straight back. Your assistant comes back with your address book and a suspicious grin on his face. Later that night, you get home and realize that someone has eaten the piece of apple pie you were saving. Thinking back you realize how foolish it was of you to give that amount of trust to your assistant. You should have never handed over the keys to something so valuable and private. You now consider yourself lucky that a piece of pie was the only thing you were robbed of. But man, you were really looking forward to that piece of pie...
A similar situation has arisen in the fast growing internet world. With the increasing number of web services out there today and their respective API's, it was bound to happen that they would want to share information with each other. There are plenty of examples of such situations. One of the more common being Facebook, or some other social communication service, such as Twitter wanting to access your e-mail address book in hopes to find 'friends'.
Somewhere along the way when this idea of sharing resources across web services crossed over into the implementation phase, someone got lazy and decided the easiest way to access these resources would be to have the user give up their credentials so that the web service could act as the user to retrieve the resource they wanted. It seemed as though other web services caught wind of the sharing web resources idea and proceeded in copying this bad implementation.
In the previous example of sharing a web resource, Facebook or Twitter will not only have access to my address book, but will have control over the entire e-mail service. They could send out invitation e-mails for their service to everyone in my address book without my consent. What is worse is the information they may acquire from my actual e-mail messages. Many web services provide ways to retrieve lost passwords by e-mailing replacement passwords to me. If I give my e-mail provider credentials away, there is a very real threat of that convenience being compromised and even more of my online services become vulnerable. Even if their intentions are good, there is absolutely no reason to give anyone but the issuing service your credentials, ever. When you do so you are putting complete trust with that service. Just like the keys and the assistant.
Solving the problem
Let's take a look at a similar problem. In the world of online credit card purchases, it seems that you are indeed practicing the same bad practice of handing over too much information regarding your credit card. Many credit card companies have ways to combat the risk involved with online purchasing. They will issue a special credit card number for the internet transaction that will only authorize for a specific amount and for the specific online store you want to purchase from. This special number is uniquely linked to you, and if someone else did happen to steal it, it would not work anywhere but that online store and for a limited amount of money.
Our problem in the internet world can be solved in a very similar fashion. We shouldn't have to put trust in the web services, because really we should never have to hand over the keys to the kingdom. That being said, lets think about the original good idea of sharing resources. It would be great to allow Facebook or Twitter access to my address book and only to my address book upon my approval and without having to give up my credentials.
An available solution
So how can this be accomplished? Well, as you may have guessed, there is a fairly new protocol that works to prevent placing too much trust into web services. It is called OAuth. What OAuth does is create a request token from the 'Consumer' web service, in this example, Facebook or Twitter. This request token is passed to the 'Service Provider', which would be my e-mail provider, such as Gmail. The request token contains a consumer key and secret which uniquely identifies the 'Consumer', Facebook. I will be redirected to a Gmail login, where upon giving my proper credentials to Gmail, I will be directed yet again to a page asking if I want to grant access to my address book to Facebook. If I agree, the request token is authorized and sent back to Facebook who can now create an access token to retrieve the information from Gmail.
As a developer, this seems like a great way for API's to share user resources. There are, however, a couple of concerns. How will this process degrade the user experience? As someone who is security conscious, I would much rather be redirected to a couple of pages than give my Gmail credentials to Facebook. However that process of being redirected can seem like an annoyance and may have end-users giving up on using the Consumer's feature. This seems to be very much the case in a society where we want our information as quickly as possible, whether it be on an mobile device, laptop, or some other electronic device. It will be interesting to see the ways in which Consumers will try and make this a more user friendly experience and how it may possibly create venues of vulnerability by misuse of the protocol. One possible implementation I'm sure I will see somewhere is the ability to keep users on the Consumer's site by handling the OAuth process with AJAX and iframes. This would make it much more difficult for an end-user to spot a potential phishing attack.
Another concern is the granularity to which the Service Providers will provide for its users over the access scope of their resources. What if I am ok with sending my address book to Facebook from Gmail but don't want my work contacts included. It would seem that this granularity would be beneficial on the Consumer side, so that an appropriate request can be made to Gmail from the start. However, if that were the case how can I be assured that the Consumer is acting on the users behalf by providing Gmail with my filtered request for the requested resource? This is why it would be more legitimate to have this type of access scope control available on the Service Provider side that provides access to my resources.
There is also the previously mentioned possibility of phishing. Who is to say that the Consumer that wants our address book is not some evil web service that is unbeknownst to us? It appears that they are using OAuth as I have been redirected to what looks like a legitimate Gmail login form and not asked for my Gmail credentials within the evil web service. The problem is that this is a phishing site and not actually Gmail. I end up giving the evil web service my credentials and they fake an OAuth access request. Now they are sending e-mails willy nilly to everyone in my address book, posing as me, wanting to invite them to use the evil web service. Requiring these web services to use SSL during the OAuth process will definitely help prevent this type of scenario. In a perfect world, users would be more cautious with sites that want authentication and would be educated on how to identify a legitimate site.
In addition to OAuth there are some other complimenting services out there that help keep trust from breaking down across these web services. OpenID provides for a single identity for the web. Using this OpenID you will be able to access all the many web services we use today, provided that they support OpenID (the idea is growing in acceptance).
OAuth seems to be a great step in resolving the password anti-pattern issue by providing a more secure way to share resources among services. Hopefully, developers will realize the danger of being a 'cookie cutter' of poorly thought implementation, implement features while upholding secure practices, and help protocols like OAuth become a mature solution by contributing to its underlying purpose. Some web-sites currently using OAuth include Google, Netflix, Yahoo!, Photobucket and more. Many web development frameworks are also making it easy to implement OAuth by providing OAuth components. Currently the protocol is at version 1.0a. Within the proposal for 1.1, OAuth plans to make some improvements. Some of these improvements include defining error codes, language support, and adding a set of defined token attributes. Information about OAuth can be found at oauth.net.