Artemis | Blog | About & Contact

2019 / 06 / 03 - PHP: Bad Idea / Good Idea (raw)

Password storing

User authentication is something crucial for every system requiring to have user accounts.

Even (especially) for small websites and businesses, it is critical to always make sure to follow good practices for maximum security.

We're not talking about some hardcore stuff, though, as the OWASP cheatsheet demonstrates.

Bad idea: plain-text storing and unfit mechanisms

Every technique below is a bad idea, resulting in very poor security.

As a developer, you musn't re-develop security mechanisms like password protection. Home-made security gives you no guarantee that your system is to be trusted, unlike provided and well-audited mechanisms, which are "almost" guaranteed safe.

If you had the technical knowledge to do so in a proper and secure way, you would be working in security anyways!

Good idea: Using the provided mechanisms, or using dedicated libraries

As a golden rule, a secure password should never be seen by anyone.

So, how do you actually do that?

Well, you won't store the password, but a derived value, commonly called a hash (note, as this can be confusing, that the value contains more than the plain hash, a lot more is done behind the scenes).

Image displaying the password_hash format

In PHP, the password_hash function does the job for you.

You'll store the value generated by the following code in database.

// Example
$hashed_value_to_store = password_hash($password, PASSWORD_DEFAULT);

As of today, the best algorithm is PASSWORD_ARGON2ID.

As much as possible, you should follow the following order of preference to choose the algorithm you're gonna use. Note that you can change at any time, it won't break your website.

  • PASSWORD_ARGON2ID: The best choice, available from 7.3 onwards
  • PASSWORD_ARGON2I: Second best choice, if you must maintain a legacy system
  • PASSWORD_DEFAULT: Third best choice, as it'll evolve towards the "current best algorithm" when you'll update
  • PASSWORD_BCRYPT: Fourth best choice, to avoid if possible (using the first two instead)

But how do you actually verify that the password the user is providing during login is the one they entered during registering?

Before you answer, no, you won't make another password_hash and compare both results.

For that, every library provides a function, and PHP provides the nifty password_verify function.

You can simply use it like the following example.

// Example, password comes from the login form, and hashed_value comes from the
// saved entry in database
$will_be_true_if_matches = password_verify($password, $hashed_value);