Hacker News new | past | comments | ask | show | jobs | submit login
How Not To Implement A Web Application That Handles External Authentication (beerpla.net)
40 points by archon810 on Feb 4, 2010 | hide | past | favorite | 33 comments



The only problem I have with this article is the insinuation that encrypting passwords in cookies is a solution to this problem. Most of the tricks you come up with to encrypt and store passwords will be broken, too.


Agreed. It's also a conceptually wrong thing to do. The password does not belong there.


I don't think the solution is to use oAuth either.

I mean, yeah, it's technically the right thing to do. But it's just shy of impossible to implement, and it presents a goofy user experience to your users.

So if all your thing does is post stuff to Twitter on behalf of your users, I think it's probably best to save yourself 40-odd hours of frustration and perplexity, and simply save their user/pass in your database. It is, after all, just somebody's Twitter account, not their banking credentials.

If you're logging into something where money can change hands, then yeah, go nuts and do the right thing. But not for some throwaway-password site where the worst thing that could possibly happen in the case of a compromise is that somebody whinges about their cat in one of your users' name.


(1) For a significant fraction of all users --- perhaps even most users --- the twitter password is the same as the gmail password. Passwords are always hazmat and should be treated accordingly.

(2) I strongly dispute the idea that OAuth is hard to implement or is goofy to use. Unlike OpenID (which is both annoying to implement and also genuinely weird to use), OAuth's interface is simply a login page and a "yes/no" dialog. Your programming environment already has a library to do the scary math bits for you.


Is OAuth hard to implement compared to OpenID? No. Tough compared to plain old stored passwords and auth headers? Definitely.

I say this as someone who's using OAuth - because it's The Right Thing To Do For My Users - but any integration with a third-party service involves a lot more logic and state storage than just asking for their account name and password on your own site. Does the code do the right thing if the user doesn't do anything on the screen you redirect them to, closes it but they then refresh your page? Or how about if they decline and the provider doesn't send them back?

All the current authentication processes are horrible hacks. Do you really believe that user's check the URL bar if I throw them at a page that looks like Twitter's login one from my OAuth app? How about if I put a look-alike in an iframe within my page?

This is something that's really hard to hack on top of the current infrastructure. I'm really hoping something that users understand (or grow to understand) is buildable, but we shouldn't pretend we're in a happy place right now.


In startup-time, anything that takes a day to do is worse than something equivalent that takes 20 minutes.

Auth'ing Twitter using a user/pass meant that I could add Twitter support to Blogabond in 20 minutes. Reading Twitter's oAuth instructions took longer than that. For the amount of geek-cred it'd buy me, and the added headache if somebody physically broke into my datacenter and stole the production server, it's just not worth the extra time to implement.

As to your first point, naturally I have absolutely no leg to stand on there. Your mom will still use her bank password for her Twitter account, and I'm a bad person for storing it.


You think it's my mom I'm trying to protect here, but it's not. It's you. You're the one who's going to lose the user table in your database. Please take my word on that. Don't let it be full of valid passwords.


Maybe a bit of an improvement over the current method of using passwords would be to take the user's username and password, immediately using them to connect the account using OAuth, and then store them no longer. This would make the connection persistent if the user changed their password, and would eliminate a lot of the risk.


I don't think I agree.

It really depends on the transaction cost of the thing implemented. If it takes a day to implement something that has a 2x signup rate that the 20 minute thing, you are clearly making a bad tradeoff.

This is engineering. There are no absolutes, just a series of tradeoffs.


This is the sort of time saver that will cost you time later, when you want to spend your time on authentication even less. Twitter is wanting to cut off basic auth because of "security issues" (http://apiwiki.twitter.com/OAuth-FAQ#Whenareyougoingtoturnof...), and while OAuth isn't required now, it likely will be soon.


This is a tragedy of the commons thing. As a web developer, you have a moral responsibility to help your users stay secure online. Teaching them that it's OK to enter their Twitter username and password on any site that asks for it (when Twitter are trying to teach them what OAuth is and why it matters to them) is irresponsible.

Sure, it's cheaper to implement. But you should be better than that.


And now that you've read the oAuth instructions, you should understand oAuth. It took me six hours to implement it for the first time, including reading the documentation. Granted, I was using a third-party library to handle the API interaction because, well, it's already been done - so why re-do it? ;)


> Auth'ing Twitter using a user/pass meant that I could add Twitter support to Blogabond in 20 minutes. Reading Twitter's oAuth instructions took longer than that.

With all due respect; I wrote a library for Kohana PHP which allowed Twitter to be used as a login in about an hour. If I'd just been integrating it would have been faster.

The beauty of Oauth is that it conforms to a specification - so any Oauth library for whatever language your working with will co-operate with Twitter.

I'd argue that the ease of implementation means that even if it saves you from one in a thousand chance of that headache it's worth it :)


Yes but how many people use the same password between all website? I was shocked recently when I saw that my mother was using the same password for a forum as her paypal account...


If you're storing people's password in plain text in your db you should make your potential users aware of this so people (like myself) can avoid accidentally using your site.


I mean, yeah, it's technically the right thing to do. But it's just shy of impossible to implement, and it presents a goofy user experience to your users.

oAuth is actually really easy to implement. I've done it several times now, never takes more than an hour.

I also find the user experience to be pretty solid too. Whats your specific complaint?

It is, after all, just somebody's Twitter account, not their banking credentials.

Problem being many people use the same password for Twitter as they do for their email.


I concur - I really like the user experience with oAuth.

As a user, you absolutely know that a) the service they're signing up for doesn't get their twitter credentials, b) they get more value out of the original service, c) they don't have to remember / make up / reuse yet another password.

It's a lot like the paypal experience... Paypal handles all the "dangerous" stuff, like billing information; the user knows that it's paypal handling it, because it's on paypal's site; when they're done paying for it, they get redirected back to the merchant. It's a workflow many, many people are very, very comfortable with. It's a far sight easier to wrap your brain around than OpenID, that's for sure.


I don't get the `shy of impossible to implement` part. It takes a good coder just a couple of hours (and maybe one hour to someone who has done it before).


Storing the username and password in the cookie is completely ridiculous, but I just want to point out that it doesn't appear as though twitter itself uses SSL either.

Unless I'm completely missing something, neither does facebook, or reddit, or hacker news, or really any other website other than my bank.

edit: I had a complete lapse of thinking here and am totally wrong about this. There are still lots of websites that do not use SSL, but twitter and facebook are not among them, nevermind.


Many websites post the forms to encrypted sites. Facebook and others do this-I haven't looked into hacker news or reddit.


It doesn't look like reddit or hacker news do.

reddit:

     <form method="post" id="login_login-main" action="http://www.reddit.com/post/login" onsubmit="return post_user(this, 'login');" class="login-form-side">
HN:

     <form method="post" action="/y">


...but reddit's only 91 lines of lisp, what did you expect?


This doesn't do any good because the page that contains the form can be transparently altered to post somewhere else by a man in the middle.


Saying that it doesn't do any good might be a bit strong - it's still vulnerable, but much less so than straight-up POSTing over an unencrypted channel.


You're right in the general case, but in the API case it doesn't matter how the form is rendered because API clients don't parse forms.


Thanks to OpenID I don't have to worry about some of that.


So they didn't want to pony up the money for an SSL certificate, hired someone who thought putting a password in browser cookies was a good idea and stored the password in clear text... Where can I buy their stock?


encrypt the username and password via a secure salted two-way hash

I wonder what that means.


Loosely translated, it means "Don't try to figure this out yourself except for fun; use a library like bcrypt instead."


Let's say that I'm implementing a login form via AJAX. After the "Submit button" click event, I fire up a jQuery ajax.get() to the auth script, and then store logged-in status as a session cookie. This seems reasonably secure except for the fact that the password gets passed plaintext via the network. Is my best option to md5() it locally via JS, before I send it over? It's for a charity website so I don't think it'll be a big target, but I don't think that excuses bad security.

Sorry if this is better for StackOverflow, it just seems appropriate here as I have gleaned some great coding tips via HN.


Yes, this will work if you want to keep from sending the password in plain text. But you should make sure you send the request via POST rather than GET and know that you are still vulnerable to replay attacks--an attacker could just sniff out the username and hash, which they could present to you and still authenticate on your site (though they wouldn't know the actual password). Also, as far as md5 hashes go, rainbow table lookups work pretty well, so hashing alone won't provide great password security.

Another way to solve your problem would be post to your auth script via SSL. From what I know of SSL (correct me if I'm wrong, please), the handshake and encrypted connection is established before any data is sent, which will protect you against sending passwords in the clear and against password sniffing.


MD5ing in JavaScript doesn't help, because the thing you're defending against is a man-in-the-middle attack. If someone can get in the middle and steal an unencrypted password, they can also get in the middle and re-write your HTML form to remove the client-side encryption code. To protect against man-in-the-middle you need SSL.


?this is hacker site?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: