Improve Basic Identity Validation

What do you think about encouraging devs to use securer authentication mechanisms?

I’m currently looking at the default IUserIdentity implementation CUserIdentity, which operates on a username/ password base. Since the framework ships with no alternative implementations and the class is used by the skeleton app generated by yiic, I bet a lot of people stick with that approach.

"THE DEFINITIVE GUIDE TO YII" already talks about the problem with plain text passwords and why it is a bad idea to save them to DB. But why not take this a step further and discourage devs to send plain text passwords over the net in the first place?

Instead of using a username/password based identity default implementation, yii2 could encourage the use of a username/password-hash based default implementation. It might be a bit problematic to turn the password entered by the user into his browser into a hash before sending it. Seems like this required a client side script (would have been better if there was a standard embedded in the browsers, but I couldn’t find anything). And of course, relying on scripts in turn means there needs to be a fallback to plain text passwords in case the user disabled scripts. So a second identity implementation like the current CUserIdentity would be needed as well. But at least this one wouldn’t be used as the default then.

Of course, this would make it more complicated to understand how yii’s authentication flow works. I’m not sure what is more important: Making it easy for yii beginners to become comfortable with the framework or adding a bit of default security. One could argue that yii as a framework only provides the infrastructure to implement whatever one needs (including auth mechanisms). But on the other hand, setting a good example wouldn’t hurt, would it?

Why https won’t help here?

It certainly does help. But I don’t think everyone has a certificate.

// EDIT:

For example, take this site: http://www.yiiframework.com/login/ ;D

I think for any serious Web application, having an SSL certificate is a must.

Without using SSL, even if you do the password hash as you suggested above, users still have the danger of having his session cookie being intercepted.

> yii2 could encourage the use of a username/password-hash based default implementation

I agree with this.

I think that this approach makes the authentication harder to understand for newcomers, but since the generator will have multiple application templates, it could be enabled for all but the most basic one.

EDIT: I was talking above about saving the hashed/salted passwords on the database, not hashing them on the client. I agree with ekerazha, the right way to solve this problem is with SSL.

The problem with cookies/ session IDs remains without using ssl, this is true. But this information isn’t as sensible as user passwords. Unfortunately, many people use the same password for different websites, so if the password is stolen, many different applications might be affected. If someone gets my sessionId, it’s only my account on that particular website the attacker has access to. And also, only until I log out.

Besides the session id, all other data in cookies can be encrypted, right?

@Ben: you have a point. I’m wondering how to implement the solution you proposed. I suppose when rendering the login form, the server also needs to insert some salt.

To be honest, I wrote that post with the digest authentication method in mind. It required some additional work compared with only hashing the user’s input and sending that to the server. But the benefit would be, that it is an accepted standard, well thought-out and documented.

I’ve never implemented it before, but I’d say the header values that were normally sent as part of the digest-challenge needed to be rendered in the login form (or otherwise made available to the javascript portion of the login procedure).

The javascript had to care for removing the entered password from the login form and prepare some hidden inputs for the fields that were normally sent as headers in response to a digest challenge.

// EDIT:

Reading through the digest specification, I wonder what remains if we reduce it to a login aproach. A lot of the spec seems to address replay attacks. Since we authenticate only once, not every request, it might really shrink down to the nonce…

In my opinion it would be hacky.

Today, the de facto standard for password hashing with PHP is crypt() http://php.net/manua...ction.crypt.php with CRYPT_BLOWFISH.

So you would need a Javascript implementation of the PHP crypt() function. Moreover, you would need a good client-side random number generator for salt generation, but Math.random() is pretty weak in Javascript engines.

Instead of trying to reinvent the wheel, if you really care about MITM attacks you should use a SSL certificate. You can buy COMODO PositiveSSL certificates for less than 8 dollars/year. If you don’t use things like HTTPS, it’s obvious that network traffic isn’t protected, that is why HTTPS exists. Moreover, if users use the same password on every site it’s their fault (and their password could be stolen from another unprotected website).

It should be clear, that the framework can’t make logins secure per se. It can’t make people use SSL certificates. It can’t make people to store only hashed and salted passwords and it can’t make people to use a particular algorithm. What it can do is providing reasonable defaults and guiding developers into the right direction.

And this is all I’m talking about. I certainly make no claims that sending hashed passwords for login is as secure as using SSL. And I don’t try to reinvent anything. In fact, these are two reasons why I mentioned HTTP digest auth. It has been written down, because people realized that sending plain text passwords is a bad idea. Still, it does not claim to be a secure solution compared to other authentication mechanisms like kerberos [1]. The issues it addresses and its limitations are clearly written down.

Besides that, I think using password hashes instead of plain text passwords is an enhancement, even if using SSL. I’ve seen too much poorly written code - sometimes bugs, other times design flaws - that simply exposed a users password, for example in log files. If those systems used an authentication mechanism which wouldn’t have made the users password available in first place, such things couldn’t have happened.

Some more thoughts about digest auth:

  • I read it back and forth yesterday and have to admit that I don’t understand it completely. Sometimes they just seem to do too much hashing and I couldn’t figure out for what reason. :(

  • The whole concept can’t be adopted 1:1, because it handles another scope. HTTP auth authenticates every request, we only want a user to authenticate himself once. So a lot of stuff like using request methods, accessed resources or nonce counters as part of the digest don’t seem to make sense in our use case.

  • Another thing we don’t need imo is the support of realms [2].

  • Using the MD5 algorithm as done throughout the RFC is probably nothing I would recommend. Even from the RFC point of view, it only acts as a default and can be replaced with any other algorithm [3].

  • Despite the last point, wikipedia claims that digest auth "prevents the use of a strong password hash (such as bcrypt) when storing passwords (since either the password, or the digested username, realm and password must be recoverable)" [4] - need to elaborate on that.

About javascript and crypto functions:

  • There is a js crypto library from the Stanford Computer Security Lab [5]. Does anyone know details about it? How good or bad it is, if there are better alternatives?

[1] http://tools.ietf.org/html/rfc2617#section-3.1.4

[2] http://tools.ietf.org/html/rfc2617#page-4

[3] http://tools.ietf.org/html/rfc2617#section-3.1.3

[4] http://en.wikipedia.org/wiki/Digest_access_authentication#Disadvantages

[5] http://crypto.stanford.edu/sjcl/

But you are not going to use the built-in HTTP digest auth (which has many limitation), are you?

At some point you probably have to send the real password. When you register your account, you have to send a password to the server. If you send an already hashed password (hashed client-side by JS) you are just moving the issue because that hashed password is actually the password :) This approach would work only for specific situations (i.e. you have a pre-filled list of accounts) and you also have to rely on Javascript for the authentication. Instead of this flawed overengineering effort, the proper method is to use SSL.

I don’t suggest to use built-in http digest auth. I suggest to use a concept that has been published and reviewed instead of coming up with some self grown solution. Digest was the method I had in mind when starting the topic, but there might be better options.

Even if you require your users to send a password (plaintext, encrypted, …) during authentication, this is still not as dangerous as requiring them to send it over and over again every time they log in. Registration is a one time process and if you want to close that gap, there are possibilities. However, that is another story, I’m talking about authentication.

One interesting thing I’ve found is SRP [1]. Sadly, I couldn’t find any production level libraries one could use. ;)


[1] http://srp.stanford.edu/

Reading to this, I couldn’t help but wonder if Ben has been on the way to re-invent public key authentication :lol: