Settings

Theme

Ask HN: Which login method do you use?

20 points by apstuff 17 years ago · 57 comments · 1 min read


I'm at the point where I need to implement login capability on my main page.

What method do you use? php with a database? cgi against a protected file? Clickpass.com like HN.

Or did you roll your own?

jmtame 17 years ago

I have always created my own. Although I've been doing PHP, I'm currently using RoR and it has a plugin that handles all of this. PHP with a database is very easy, especially if you use CodeIgniter, there are form validation helper classes.

On registration:

- Ask for username and password (do form validation, ie passwords match, xss clean, etc). toLowercase() the login.

- Create a hash of some type for the password. This becomes used in the database, and again on login. If you're not worried about security, md5 your password, store it in the db. Otherwise, look up a salt hash.

- I typically log the user out and then require them to log in and create a session after they registered.

On login

- Ask for username and password, toLowercase() the login when checking

- Run the same md5 or salt hash against the password, check if the # of rows in the database is > 0, if it is, log the person in and give them a session with a value of "is_logged_in" to true or something similar. Also pull the database user_id or e-mail and use that to remember which user you're dealing with.

- If the # of rows found in database is == 0 (where the login and pass equal those from your post variables), the login failed

  • tptacek 17 years ago

    Please don't just use MD5 or SHA1 with a salt.

    http://www.matasano.com/log/958/enough-with-the-rainbow-tabl...

    • thorax 17 years ago

      I upvoted you because that's a good link and good advice in a sense. I don't agree fully with your exact phrasing and would put it a bit milder for someone asking this kind of question.

      I'd personally advise: Use a respected library or at least an MD5 or SHA1 approach with a strong salt. There are better ways that you should consider (link), especially if you're writing an authentication package for reuse by others.

      • tptacek 17 years ago

        It's painful to see someone recommend "at least" MD5+salt, when that solution is a single for() loop away from being at least adequate. If you're wondering why I'm using such strong words, it's because you talked about "strong salt" (which means nothing), but ignored stretching, which actually does improve security.

        SHA1+"strong salt" is extremely weak. It mitigates only one attack, which every respected authentication system has been invulnerable to since the '70s. I blame Microsoft for reviving rainbow table lore, but still, thorax. Come on.

        • thorax 17 years ago

          Your article is great advice. As I worded it, I'm providing practical advice to a new web developer. Let me elaborate on my position:

          First and foremost, don't write the password handling yourself if you can avoid it. If you do it yourself, I'm only firing the developers who put the password in plain text, and I'm not even going to give grief to the ones who at least use a rainbow-dodging salt and hash (like what most major web frameworks include by default for user auth management). I.e., if they use django defaults or Code Igniter defaults, then they're not in trouble.

          Any senior engineers on the team are going to get some whining from me if the framework supports crypt/bcrypt and they didn't enable that, but if they forgot and the site launched without it, I'm not going to die.

          It the team is making an authentication package for a web framework or especially for a native framework, they need to consider heavily using bcrypt (or other state-of-the-art approaches) for password handling unless there's some major compelling reason we cannot or should not.

          What I'm trying to be is realistic and give the guy a side that's non-religious.

          I agree with you as a hacker, but on the practical side, no coding decision is all-or-nothing with me.

          If you're a new developer and have read this far and want to know where to find decent bcrypt packages for your favorite language, Google's AWT page has a good explanation and handy links to those (scroll down):

          http://code.google.com/p/google-web-toolkit-incubator/wiki/L...

          Also here's instructions for using crypt with Django auth:

          http://docs.djangoproject.com/en/dev/topics/auth/#changing-p...

          • tptacek 17 years ago

            Two responses.

            First, we don't have pages and pages of comments and discussions because the topic isn't cut-and-dry. The topic is cut-and-dry. It just takes 5-10 round trips to explain to someone why clientside Javascript crypto is a bad idea.

            Second, I agree with you. I'm not firing someone for using SHA1+nonce. But I will bitch if you recommend it, because even though it's not a game-over mistake, it's still a mistake.

    • siong1987 17 years ago

      Rainbow Table is unavoidable. Block those IPs which have more than certain times of failed password. And, people usually cannot access to those hashed passwords.

      • tptacek 17 years ago

        Three sentences, three fallacies.

        (1) Not only are rainbow tables avoidable, but they've been trivially avoidable since Unix crypt(3) was invented in the '70s. The only way you can become susceptable to them is if you make the mistake of designing your own scheme. So don't do that.

        (2) There's a reason that no mainstream consumer application actually does this: as soon as you lock a normal user out of their account for an hour, you probably lose the user forever. Ok, there are two reasons: this technique doesn't add any security. Anybody nuts enough to brute-force your login page has as many IPs as they want. But that's not how they do it.

        (3) People get to access password hashes as soon as you mess up a single database query. The idea behind storing safe hashes is to prevent your stupid mistakes from screwing over every one of your users. The stupidest people of all are the ones who assume they aren't going to make stupid mistakes.

        • siong1987 17 years ago

          Security is an never ending war. It is evolving. And, there is always a way to crack whatever you want(it may take time). But, the question is: do you really have to waste so much time on secure something? Or, you can use your time to implement something useful.

          You are right. Use whatever auth system which is available.

        • jmtame 17 years ago

          I think it's more of an issue of what is most pragmatic. Do you know how many hour-long conversations I've had on freenode about the best method to generate hashes? At the end of the day, most people are not targets of the Russian Mafia. And a lot of people are building something that might never get used by more than 50 people, so they don't care. If you're a Department of Defense contractor, I could understand why you would go out of your way.

          I think it's fine if you block IPs after they've hit a fail threshold for logins. Or at least freeze the account for a certain period of time (see failed iPhone login attempts).

          • tptacek 17 years ago

            Think about what you're saying. "Security doesn't matter for these applications because they have almost no users, so we'll do something that will royally piss off the few users we're desperately trying to retain, and which will add no security. What's more, by implementing it ourselves, we'll pay extra to do that."

            I agree with you. People talk about this stupid hashing thing far, far too much. Especially because there's already a "right answer". Just use whichever auth plugin is most popular and provides bcrypt.

        • weavejester 17 years ago

          You're correct that rainbow tables are trivially avoidable, but it shouldn't take a single stupid mistake to expose your database. Password hashing is a last line of defense, not something that should ever be necessary unless something has gone very wrong indeed.

          • tptacek 17 years ago

            It shouldn't take a single stupid mistake to turn a string copy into a passwordless remote software update mechanism. $3+Bn USD of "shouldn't", down the drain.

            Can we talk about the real world, now? The reason Microsoft is driving modern offensive computing researchers nuts isn't that they got rid of the "stupid errors"; it's that they figured out how to make the runtime mitigate those errors with ASLR, NX, safe exceptions, and checked heaps.

            In the real world --- and I am speaking from bitter and recent experience with very, very, very smart clients here --- you should assume you are going to make stupid mistakes, and do everything you can reasonably do to keep those mistakes from totally screwing over your customers.

            • weavejester 17 years ago

              Could you give an example of a stupid mistake that could expose the database? SQL injection attacks are pretty hard to accidentally put into any reasonably well-built system, so I'm curious if you know of any other mechanism through which you could entice a database dump out of a web application.

              I guess you could go after the OS or the web server, but I was under the impression you were talking about stupid mistakes from the web developer, not the developers of the OS or web server.

        • yesimahuman 17 years ago

          "(2) There's a reason that no mainstream consumer application actually does this: as soon as you lock a normal user out of their account for an hour, you probably lose the user forever."

          I don't know, it seems to work pretty well for Microsoft

dryicerx 17 years ago

Since most people already talk about the backend of it, let me share how to securely send the password from the browser to the server encrypted, instead of simply in clear text. (when you can't use SSL for some reason)

+ Server has your passwords stored as sha1(password+salt(password)). salt function isn't secret (eg. reverse the text)

- Client visits login page

- Website generates random token. Then sends back HTML with the random token

- Client generates passresponse = sha1(token + sha1(password + salt(password)))

- Client sends the passresponse, token, and username back

- Website checks for existence of token, removes it, then computes it's own sha1(token + password_hash_from_db) and checks against the sent passresponse.

This way the password is never sent in clear text. Unlike HTTP authentication, this works nicely with html forms since you can do all the crypt in js. Then again, this might be a bit overkill... and using SSL is probably a better option.

Just sharing another solution.

  • tptacek 17 years ago

    You're describing the simplest possible challenge-response scheme. It has two problems, both severe enough that you shouldn't recommend people waste time implementing it:

    * First, because no browser bakes this crypto protocol in, you have to deliver it over Javascript. The protocol basically stipulates that you don't have SSL/TLS. So all you've done is move the goalposts. No matter what kind of dance you do (for instance: Meebo actually delivers a JS implementation of RSA!), the action is now in the JS delivery, which is trivially compromised.

    * Second, secure authentication schemes aren't vulnerable to trivial dictionary attacks. This one is: the attacker is stipulated to have access to your traffic. She sees the nonce the server sends and the hash the client responds with. She can solve for the password by (very fast) brute force against a wordlist.

    • dryicerx 17 years ago

      To your first point, yes js would be doing the crypt, if the js delivery can be compromised, then the login html delivery can be equally compromised (which would send the login information somewhere else)

      I agree with your second point, a eavesdropped can use a dictionary attack. It makes it just a tiny bit harder for them since they need to generate their own cleartext-crypttext and cannot use a pregenerated table.

      I am curious, is there a better way to do this (other than SSL or using RSA)

      • tptacek 17 years ago

        In that first sentence, you need to take the we word "if" out. The exact same attack that motivated you to come up with the challenge-response scheme works against the JS delivery.

        In the third sentence, take the "or RSA" out. There's no way to get a browser to safely do RSA authentication without SSL.

        I have good news for you. The answer to this problem doesn't involve complex technology. What security practitioners are going to recommend to you is, just put up a login page, and send usernames and passwords. I have just released you from having to waste time and energy thinking about this.

  • lsc 17 years ago

    sure sounds like you've re-implemented http digest authentication.

    http://en.wikipedia.org/wiki/Digest_access_authentication

    • dryicerx 17 years ago

      That's what I had been using earlier, problem with that is the ugly login box the browsers prompt (there is no way to integrate HTTP Authentication in to HTML)

      • lsc 17 years ago

        ah. well, I obviously have a very poor sense of aesthetics (look at my webpage- it would have been ugly in 1995) but thanks, that answers my question. (my question is "why don't people use http auth anymore?)

        I really like http auth because it's a system level solution, and I'm the computer janitor; I know where the problems with http auth are without wondering if the dev who wrote the webapp made a mistake or not.

tptacek 17 years ago

Most every web application my team assesses just uses a database of hashes. This is fine; just try to make the hash function take a long time to run (speed is the enemy here). I highly recommend "bcrypt", a routine available in almost every dev environment --- and typically in the better plugins --- for generating safe auth hashes.

mk 17 years ago

django.contrib.auth

modoc 17 years ago

I have my own code I use on my projects. It uses secure SHA 256 hashing for the passwords. The code handles registration, login, logout, and forgot password flows.

  • e1ven 17 years ago

    We pass the login and passwords to an openldap server running internally, and then get back the success/fail message.

    This is the best strategy for us because it allows us to offer a wide array of services running through our accounts, using out of the box software..

    We can tie the forums into LDAP without writing our own, as well as our internal Jabber server, etc.

    Once login has completed, we give the user a 128-bit sessionID, which we use for all further communication, until their session expires.

  • Confusion 17 years ago

    As opposed to insecure SHA 256 hashing?

    Anyway, if you don't use a nonce per user or a time consuming hashing method, then all tptacek's comments apply. His link in http://news.ycombinator.com/item?id=576021 is worth your time.

kineticac 17 years ago

Just put the TwitterAuth gem into my rails app, and am using OAuth with twitter now. This is a niche though, meaning unless you already have twitter, or actually like it, it's a long process and could keep people from signing up. Logging in is easy though.

http://kineticac.posterous.com/rails-and-twitter-signin

javanix 17 years ago

I am working rolling my own with Struts/JSP.

It seems pretty straightforward (hash pass, place on server, and check against), but I need an easy way to compute an SHA hash in-browser, so the server doesn't have to receive the pass in plaintext.

Anyone know of a way to do it with Struts/JSP, or even JS if its not too slow?

  • tptacek 17 years ago

    This is kind of silly:

    * The hash you send will probably be password-equivalent; losing it to an attacker is just as bad as losing the password.

    * If you're delivering the JS to generate the hash over HTTP, you have exactly the same threat model as with plaintext passwords (attackers will just subst a script that sends the raw password).

    * If you have working HTTPS, you already have optimal communications security; just send the password.

    * Even if you came up with a challenge-response protocol to make the hash non-replayable, the exchange itself would be vulnerable to a trivial dictionary attack.

    Don't bother with this idea. Move on to something that will add real value to your app.

lsc 17 years ago

I use http auth

apache has modules to hook it up to just about any backend; it's supported by all browsers, and it's easy to automate against.

I would be interested in knowing why more people don't use it.

  • tptacek 17 years ago

    Because, at least with mainstream browsers, users can't log out.

    You can fail certain formal security audits for using HTTP authentication.

    • lsc 17 years ago

      Speaking of the audit problem, do you have a link? is this just for http basic? or is this the case for http digest as well? what about negotiateAuth with mod_auth_kerberos or the like? is this only because of the logout problem? or because of the problems with basic auth?

      hm. I know you can logout by going to https://username:boguspassword@thesiteyouarelogingoutfrom.co... but that will ask you to re-input your password, usually, making it unsuitable for a 'logout' button usually, I think. I wonder if there is a js workaround for that.

kineticac 17 years ago

We're using Rails as the framework and restful_authentication plugin for logins. Moving forward we are also going to integrate OAuth for things like Twitter logins, Facebook Connect for facebook, etc.

SemperUbi 17 years ago

HTTP Basic + https

  • lsc 17 years ago

    how come you don't use http digest? http://en.wikipedia.org/wiki/Digest_access_authentication it is significantly more secure without https

    • tptacek 17 years ago

      Because digest requires you to store the plaintext of the password on the server, making any database or filesystem exposure a calamity for all your users.

      • lsc 17 years ago

        do you think a hashed password is going to last long against an attacker? considering how cheap computing resources are (and the common use of botnets, and the fact that most passwords are dictionary words) I treat password hashes as if they were cleartext passwords.

        But I suppose that if you are using https, you get most of the advantages of digest anyhow.

        • tptacek 17 years ago

          If the password is hashed well, with stretched SHA1/SHA256 or (better yet) bcrypt, then yes: breaking the hash would involve a significant advance in cryptography.

          • lsc 17 years ago

            hm? I'm trying to say that once you have the hash, you can run a dictionary attack against it without any advances in anything. I can use whatever procedure the server uses to verify logins, and just try passwords. You can make the dictionary attack more expensive by using an expensive hash like bcrypt, but that's going to slow down your app, too. (http auth re-authenticates every page load.) so really, you can't make your hash calculation any slower than, say, 50ms without users complaining.

            Lets say you can crack the average user account with 40,000 hits from a dictionary attack (I imagine most passwords fall much faster) if each lookup takes 50ms, 20 lookups a second, it'll take around 30 minutes of cpu time to crack each password. assuming a reasonable-sized botnet, that's not much.

            • tptacek 17 years ago

              You're not thinking this through. In no well-designed web application is password checking in the 80/20 hotspot of performance. In fact, if it's within a light year of mattering to performance, you've done something horribly wrong.

              The point of adaptive hashing is that doubling the cost of the hash on the serverside adds negligable overall cost, but doubling the cost of the hash on the attacker's side doubles their cost. This is not a complicated tradeoff.

              • lsc 17 years ago

                hmm? http basic auth checks your password on every request. you can do auth other ways, (but you need to be very careful.) but that's how http basic auth works.

                the attacker can check one word from her dictionary in the same amount of time it takes you to authenticate one user for one page.

                if you make that check take longer than 50ms, it will start slowing down your webapp.

                at 50ms, an attacker can check 40,000 words in around half an hour.

                you can double that to 100ms, but at that point you are starting to slow down page loads, and it's still only taking the attacker an hour to run through that dictionary.

                • decode 17 years ago

                  On average, the attacker will have to search half of the hash space to find a given password. So, your 40,000 searches is way too small as long as you require more than 2 character passwords. If you assume lowercase + uppercase + numbers for the passwords, and require at least 6 characters, you get

                  (26 + 26 + 10) ^ 6 = 56,800,235,584 combinations

                  searching half of that would be about 28 billion combinations. At 50ms each, that would take 388,888 hours, or 44.36 years.

                  • lsc 17 years ago

                    if passwords are randomly generated, I agree with you completely, and everything I've said is crazy talk.

                    But most passwords are not randomly generated. Most passwords are dictionary words, or two dictionary words. You don't need to search the hash space; you only need to search the password space, and if everyone uses the name of their dog, well, that's not a very large space.

                    http://www.schneier.com/blog/archives/2006/12/realworld_pass...

                    • tptacek 17 years ago

                      If passwords are two dictionary words, then even with the system dictionary, a single 50ms hash takes 889,251 hours to crack. 8 million if people put a single digit at the end of it. You won't win this argument.

                      • lsc 17 years ago

                        adding two dictionary words and a number, yeah, that helps a lot. looks like you are right, and that if your users use 2 words and a number, and you use a hash that takes 50ms to calculate, you are probably OK.

                        but my point is that passwords are a lot less secure than they sound if you just add up the characters. And most hash functions take a whole lot less than 50ms of cpu time to calculate. Bcrypt does look pretty cool in it's ability to slow down brute force attacks. It does still require a minimum amount of entropy in the user passwords, though.

                • tptacek 17 years ago

                  Don't use basic auth, lsc.

                  [Edit] I regret even conceding this point. Even if you use basic auth, the tradeoff here is not complicated.

                  • lsc 17 years ago

                    the bigger point is that there is a limit to how slow you can make the password checking process. Ok, so let us assume you securely authenticate once per session. How long can that authentication take? I suppose you can put up a little clock... make it take a second and we are talking 11 hours per password, which is starting to get significant... but my point is that the small search space provided by user chosen passwords means that if you make the hash function slow enough to stop an attacker, you are moving into time spaces that users will notice.

matticakes 17 years ago

http://www.openwall.com/phpass/

dmanxiii 17 years ago

OpenID, if applicable.

  • frossie 17 years ago

    Comment from the user end: I am not the greatest fan of OpenID (try talking your grandma through getting one) but I agree that as long as you don't have a site where the user might have a real need for unique authentication information (eg. bank account), you should really consider something like clickpass.

    I always try new sites if I can get in with existing authentication - and I don't always if I need to register. So it depends how much you care about uptake.

rincewind 17 years ago

ssl client certificates

  • tptacek 17 years ago

    I can't understand why making SSL client certs a totally seamless experience for end-users isn't the #1 security priotity for the IE and Firefox teams.

rguzman 17 years ago

facebook connect

  • coopr 17 years ago

    Anyone have any pros or cons of Facebook Connect? Besides the obvious con of requiring your users to be Facebook users too?

zmonteca 17 years ago

We used a combination of Cake Auth

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection