-2

The following code should be straight forward and simple, the insert into the db on signup creates a hash, but later when I try to login with the same password the hash it is creating isn't matching up to what is in the database (I had print_r's throughout to verify). Can someone see if I'm just overlooking something dumb?

session_start();
require_once("login.php");
$error = "";
$email = "";
$password = "";

if (isset($_GET['logout'])) {
    unset($_SESSION['id']);
    setcookie('id', '', time() - 60*60);
    $_COOKIE['id'] = "";
} else {
    if (isset($_SESSION['id']) or isset($_COOKIE['id'])) {
        header("Location: loggedinpage.php");
    }
}

if (isset($_POST["submit"])) {
    $link = mysqli_connect($hn, $un,$pw,$db);
    if($link->connect_error) die("Fatal Errror.");
    if (!$_POST["email"]) {
        $error .="An email address is required<br>";
    }
    if (!$_POST["password"]) {
        $error .="A password address is required<br>";
    }
    if ($error != "") {
        $error= "<p>There were error(s) in your form:</p>".$error;
    } else {
        if ($_POST['signup'] == 1) {
            $email = mysqli_real_escape_string($link, $_POST['email']);
            $password = mysqli_real_escape_string($link,$_POST['password']);
            $query = "SELECT id FROM `users` WHERE email = '".$email."' LIMIT 1";
            $result=$link->query($query);
            if (mysqli_num_rows($result) > 0) {
                $error = "That email address is taken.";
            } else {
                $hashedPassword = password_hash($password, PASSWORD_DEFAULT);
                $query = "INSERT INTO `users`(`email`,`password`) VALUES ('".$email."', '".$hashedPassword."')";

                if (!mysqli_query($link,$query)) {
                    $error = "<p>Could not sign you up, please try again later</p>";
                } else {
                    $_SESSION['id'] = mysqli_insert_id($link);
                    if(isset($_POST['stayLoggedIn']) and $_POST['stayLoggedIn'] == 1) {
                        setcookie('id', mysqli_insert_id($link), time()+60*60*24);
                    }
                    header("Location: loggedinpage.php");
                }
            }
        } else {
            $email = mysqli_real_escape_string($link, $_POST['email']);
            $password = mysqli_real_escape_string($link, $_POST['password']);
            $hashedPassword = password_hash($password,PASSWORD_DEFAULT);
            $query = "SELECT * FROM users WHERE email = '".$email."' LIMIT 1";
            $result = $link->query($query);
            if ($result->num_rows > 0) {
                $row = $result->fetch_array(MYSQLI_ASSOC);
                if ($email == $row['email'] and password_verify($password,$row['password'])) {
                    if (isset($_POST['stayLoggedIn']) and $_POST['stayLoggedIn'] == 1) {
                        setcookie('id', $row['id'], time()+60*60*24);
                        header("Location: loggedinpage.php");
                    }  
                } else {
                    $error = "Incorrect Username/Password combination";
                }
            }
        }
    }
}
Funk Forty Niner
  • 74,450
  • 15
  • 68
  • 141
zsebacher
  • 11
  • 1
  • 1
    It seems to be a debugging issue. You may have a peek on this [article](https://ericlippert.com/2014/03/05/how-to-debug-small-programs). – Amessihel Nov 22 '18 at 15:50
  • https://stackoverflow.com/a/268269/10111639 – TsV Nov 22 '18 at 15:51
  • It would be better to use prepared statements instead of manually concatenating the strings. Or just use a proper PHP authentication library and don't reinvent the wheel on user registration / authentication. But like others said, in order to help yourself, show what you've tried and where you got stuck while debugging. – slhck Nov 22 '18 at 15:52
  • 2
    You are hashing the escaped password instead of the entered one. But as you are doing this also when verifying, this should cancel out. You also don't need the `$email==$row['email']`, as you already search for this email in the database query, although the DB search would be case insensitive, and this comparison is case sensitive. Did you enter the E-Mail with same case when logging in? – Karsten Koop Nov 22 '18 at 16:02
  • 1
    Please confirm the type and size of the database column where you're storing the hashes. – miken32 Nov 22 '18 at 16:40
  • @miken32 sorry had to to head straight to thanksgiving before posting it. Thank you though I believe now it was an issue with the column size of the password being hashed. Going to try to fix that – zsebacher Nov 22 '18 at 21:31
  • Can you confirm the size and type? – miken32 Nov 22 '18 at 21:32
  • email is varchar(50) and I changed the password to varchar(255), it was previously at 50 as well, but still getting the same issue. – zsebacher Nov 22 '18 at 21:44
  • It now works but only when I have the stay logged in checkbox clicked. Note I did remove the header redirect down a level. I realize when I posted it was contigent on the stay logged in to be checked, but after moving it from there it won't seem to redirect unless I have that box checked. – zsebacher Nov 22 '18 at 21:54

2 Answers2

1

Although it's tucked away at the end of a paragraph, PHP documentation does say that "it is recommended to store the result in a database column that can expand beyond 60 characters (255 characters would be a good choice)."

The current default algorithm, bcrypt, generates hashes that are 60 characters long. If your database column cannot hold at least this many characters, your hashes will be truncated and verification will fail.


You've got a few other problems as well:

  • You're modifying the password before generating the hash (with mysqli_real_escape_string())
  • You're not using prepared statements
  • You appear to be relying on cookies for authentication. Cookies are user-generated data, they are not to be trusted! This is why PHP provides session support, because the data is stored on the server.
  • You should not be checking for an existing email address using a query, instead you should have a unique index set on the email column in the database.
miken32
  • 42,008
  • 16
  • 111
  • 154
-1

try

  if(password_verify($password, (string)$row->password)){
             //Your Code
            }

because of password_verify function return Boolean only true or false

And

$hashedPassword = password_hash($password,PASSWORD_DEFAULT);

Only add once when you Insert to Sql (new user)

Abdullah Ockba
  • 124
  • 1
  • 2
  • 8