How *Not* To Implement A Web Application That Handles External Authentication, Using BeTwittered.com As An Example
Today I'm going to look at how not to handle user authentication in a web application, taking BeTwittered.com authenticating with Twitter as an example (sorry, guys).
BeTwittered is a simple and comfortable gadget that you can add to your site, such as your iGoogle homepage.
Since BeTwittered is just a bridge between you and Twitter, it has to first log you into your account. Here is where things go horribly, horribly wrong.
1. BeTwittered does not use SSL to secure requests to its servers
All authentication information is transmitted to BeTwittered servers in plain text and is easily sniffable by an attacker, both on your own network and outside of it. You can read more about SSL encryption here.
Since BeTwittered passes your Twitter username and password unencrypted as GET parameters, it may as well be serving them to potential attackers on a silver platter (note that passing this data in a POST request would change nothing, security-wise).
Here is an example request:
http://betwittered.com/api/?_=1265242511260&req=verify_credentials&username=foo&password=bar
Ugh…
2. BeTwittered stores your username and password in unencrypted cookies
Because BeTwittered tries to keep you logged into Twitter, it caches the username and password, unencrypted, inside browser cookies.
This means that an attacker needs to simply look at your cookies to steal this information. This can be done using these methods, among others:
- using an XSS vulnerability
- sniffing the network traffic
- walking up to your computer
3. Because BeTwittered passes your authentication information to its servers, it's already insecure
If someone gets access to BeTwittered servers, it's safe to assume at that time that all accounts are potentially compromised.
Smaller sites generally cannot dedicate appropriate resources to securing their servers, which can make breaching them easier for hackers. Even Twitter itself was hacked numerous times.
The Alternative Solution
oAuth
If the endpoint application supports oAuth (Twitter has for months), do us all a favor and use it. Please.
oAuth allows delegating authentication to Twitter itself and only giving the application easily revokable limited access.
If BeTwittered were using oAuth, the user would be redirected to Twitter, where he or she would login. Then, the user would be sent back to BeTwittered, but now bearing special tokens. Any requests to Twitter would then be accompanied by these tokens, which would be validated by Twitter every time they're used – all of this without ever passing your password around.
You can find a nice overview of the oAuth architecture here.
Otherwise
If the endpoint application doesn't support oAuth, then
- use SSL encryption (https)
- store the authentication information on the server side instead of the client side in a cookie. Instead, use the cookie to store some sort of an internal ID pointing to this server-side data. Alternatively, encrypt the username and password via a secure salted two-way hash and only then store the encrypted version in a cookie
- make sure to stay on top of securing your servers (and give your sysadmin a raise). It's a time-consuming commitment, please take it seriously
Conclusion
What other secure authentication technique or tips do you know about? Feel free to share in the comments.
Oh, and this goes without saying – stop using BeTwittered, at least until they implement a more secure login option. I've alerted the creators about the issue and also started these threads on HN and Reddit.
In the meantime, if you found this article useful, feel free to buy me a cup of coffee below.