1

I have added the password_hash PHP function to my registration page, where users create accounts and store passwords. I applied the same password_hash line of code in the registration form. The data is saved in the database, but when I try to log in, the password submitted isn't matching the password stored. I also tried the password_verify function, which I read in the PHP manual, but nothing works. I really don't know what else to do, after trying and trying, so if anybody has an advice, I'd appreciated it.

P.S. I'm currently using PHP version 5.6.25.

Here's the code:

<?php
// AJAX CALLS THIS LOGIN CODE TO EXECUTE
if(isset($_POST["e"])){
    // CONNECT TO THE DATABASE
    include_once("PHP_Includes/db.php");
    // GATHER THE POSTED DATA INTO LOCAL VARIABLES AND SANITIZE
    $e = mysqli_real_escape_string($db, $_POST['e']);
    $p = password_hash($_POST['p'], PASSWORD_DEFAULT,['cost' => 15]);
    // FORM DATA ERROR HANDLING
    if($e == "" || $p == ""){
        echo "login_failed";
        exit();
    } else {
    // END FORM DATA ERROR HANDLING
        $sql = "SELECT id, username, password FROM users WHERE email='$e' AND activated='1' LIMIT 1";
        $query = mysqli_query($db, $sql);
        $row = mysqli_fetch_row($query);
        $db_id = $row[0];
        $db_username = $row[1];
        $db_pass_str = $row[2];
        if($p != $db_pass_str){
            echo "login_failed";
            exit();
        } else {
            // CREATE THEIR SESSIONS 
            $_SESSION['userid'] = $db_id;
            $_SESSION['username'] = $db_username;
            $_SESSION['password'] = $db_pass_str;
        }
    }
    exit();
}
?>

login() function:

function login(){
    var e = _("email").value;
    var p = _("password").value;
    if(e == "" || p == ""){
        _("status").innerHTML = "Fill out all of the form data";
    } else {
        _("loginbtn").style.display = "none";
        _("status").innerHTML = 'please wait ...';
        var ajax = ajaxObj("POST", "index.php");
        ajax.onreadystatechange = function() {
            if(ajaxReturn(ajax) == true) {
                if(ajax.responseText == "login_failed"){
                    _("status").innerHTML = "Login unsuccessful, please try again.";
                    _("loginbtn").style.display = "block";
                } else {
                    window.location = "user.php?u="+ajax.responseText;
                }
            }
        }
        ajax.send("e="+e+"&p="+p);
    }
}
Millica
  • 168
  • 12
  • Where's your attempt using `password_verify()`? That's what you need to use. `password_hash()` will give you different results each time it is called. – Patrick Q Sep 15 '16 at 21:16

1 Answers1

4

Your understanding of how password_hash() works is a bit off. Unlike using sha1() or md5() (both of which you should avoid for storing passwords!), the password_hash() doesn't return the same string for every time it's called, even for the same string.

For example:

var_dump(password_hash("hello_world", PASSWORD_DEFAULT));
var_dump(password_hash("hello_world", PASSWORD_DEFAULT));

would output (for example, the strings returned by password_hash() varies for each time its called)

string(60) "$2y$10$Da2HG0dcvfI.3qBivR8Mpu9U5S06PBZ3415lDEh3EcDZ/fELZzHgC"
string(60) "$2y$10$zL6745UkPEvZWS5w1Keco.IKi7ssl.PqldGxucDYHaJW3vgCc366a"

Notice that they are different, even when the function is called twice on the same value? This means, that you cannot compare the stored password against $p = password_hash($_POST['p'], PASSWORD_DEFAULT,['cost' => 15]); like you are currently doing, because the password_hash() function returns a different string every time - you need to use the function password_verify() to verify the password, like below

$p = $_POST['p'];

if (password_verify($p, $fromDataBase)) {
    // Valid password!
}

So instead of...

$p = password_hash($_POST['p'], PASSWORD_DEFAULT,['cost' => 15]);

you want

$p = $_POST['p'];

and instead of...

if($p != $db_pass_str){

you want

if (!password_verify($p, $db_pass_str)) {

And two notes on security:

  1. You are not using prepared statements, which you REALLY should! See a link for mysqli_prepare() below. You should treat all your user-input as dangerous, and therefor use prepared statements for all SQL queries that accepts user-input. (When using prepared statements, you don't want to use mysqli_real_escape_string() - use one or the other, most preferably prepared statements!)

  2. You are storing a password in a session - this is highly discouraged, as sessions can be "hijacked".


Readingmaterial:

Community
  • 1
  • 1
Qirel
  • 25,449
  • 7
  • 45
  • 62
  • 1
    First of all, wow!! Thank you so much for your reply. It's like the best reply I've ever gotten! Thank you! I made the changes as you suggested, however after making the changes, my page stopped loading. The server is fine, and other pages are fine, but that one page with the code isn't working anymore. After investigating what happened, the line of code `if (!password_verify($p, $db_pass_str)` is the problem. Not sure what to make of this. Any ideas? – Millica Sep 15 '16 at 21:41
  • Ah, yes - that's my bad, I made a typo when typing up the answer. It should be like `if (!password_verify($p, $db_pass_str)) {` (there's a missing `)` after the `if` causing syntax errors). I'll update the answer too! – Qirel Sep 15 '16 at 21:42
  • Ahhh!! I should have seen that! I'm really tired, so that's my excuse. :D Btw, I tried the code and it works!! Just today I started to learn about the password_hash function and I'm thankful that you brought some things to my attention. I'm teaching myself, so your advice is appreciated. Thanks again for your help!! :D :D – Millica Sep 15 '16 at 21:48
  • Happy to have been of help! Glad you sorted it out :-) good luck with your continued programming and learning ;-) – Qirel Sep 15 '16 at 21:51