So I have a Registration page and a Login page, the registration page works perfectly fine but the Login page doesnt seem to work and I cant seem to figure it out.
My database seems to be working as I am able to echo out the hashed password onto the page of the login, it seems to have something to do with
password_verify()
Registration Page (Working)
<?php
include("assets/includes/conn.php");
$user = $_POST['username'];
$pass = $_POST['pass'];
$cPass = $_POST['c-pass'];
$email = $_POST['email'];
$options = [
'cost' => 11
];
if($pass == $cPass){
$stmt = $conn->prepare("INSERT INTO users (username, pass, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $user, $h_p, $email);
$user = $_POST['username'];
$h_p = password_hash($pass, PASSWORD_DEFAULT, $options)."\n";
$email = $_POST['email'];
$stmt->execute();
echo "Created";
echo $h_p;
$stmt->close();
$conn->close();
}
Login Page (Not working)
<?php
include("assets/includes/conn.php");
$username = $_POST['username'];
$password = $_POST['pass'];
$sql = "SELECT * FROM users WHERE username = '$username'";
$result = $conn->query($sql);
if ($result->num_rows == 1){
$row = $result->fetch_assoc();
$hash = $row['pass'];
if(password_verify($password, $hash)){
echo "Yes";
} else {
echo "No<br/>";
echo "" . $hash . "<br/>";
echo $password;
}
}
The problem here is that the \n in:
$h_p = password_hash($pass, PASSWORD_DEFAULT, $options)."\n";
^^
is (invisibly) adding a carriage return/linefeed at the end of your password/hash.
You can either remove it.
$h_p = password_hash($pass, PASSWORD_DEFAULT, $options);
or trim() it:
$h_p = password_hash($pass, PASSWORD_DEFAULT, $options)."\n";
$h_p = trim($h_p);
I honestly don't know why the manual on password_hash() doesn't make a mention about it and the usage of it for storing it in a database (or a file).
NOTE: What the docs haven't used here, was to assign a variable to the example, which is what was done in the question here. Some may think that using the example and assigning a variable to it will work; it won't; not for storing the hash and then verifying it after.
The example from the manual reads as:
echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT)."\n";
But doing:
$var = password_hash("rasmuslerdorf", PASSWORD_DEFAULT)."\n";
will in fact (theoretically) contain a 61-length string (because of the concated linefeed character), instead of the intended 60 without the linefeed character.
So now you need to clear out your present hashes and start over with a new set of hashes.
Have a look at this sandbox code example
When run, it will output something like this:
$2y$10$494GPYzaynEkfYxE3wcAj.OtwBU3CCwTMXOHKbdJmOqwMXRmq6v1u
61
Just in case the URL's a 404 later on, here's the code for the above:
<?php
$foo = password_hash('mypass', PASSWORD_DEFAULT)."\n";
echo $foo;
echo strlen($foo);
On an added note; you should also use a prepared statement for your SELECT just as you did for the INSERT; it's much safer.
Related
I am working on making a login section for my project website using PHP, but for some reason, verify_password won't return true, even when I am giving the correct password. No idea what I am doing wrong here.
Here is the code that I use to add the user to the MySQL table:
$password= $_POST['password'];
$hash = password_hash('$password', PASSWORD_DEFAULT);
// I know this isn't inject proof
$res = $conn->prepare('INSERT INTO login (SSN, UserName, passhash) VALUES (:SSN, :UserName, :passhash)');
$res->bindValue(':SSN', $_POST['UserName']);
$res->bindValue(':UserName', $_POST['UserName']);
$res->bindValue(':passhash', $hash);
$res->execute();
It stores the hash in a varchar(60)
Here is the code that takes the password, and verifies it against the hash:
$userName = $_POST['UserName'];
$password= $_POST['password'];
// I doubt this is inject proof
$res = $conn->prepare("select passhash from login where UserName='$userName'");
//$res->bindValue(':SSN', $_POST['UserName']);
//$res->bindValue(':UserName', $_POST['UserName']);
//$res->bindValue(':hash', $hash);
$res->execute();
$result = $res->fetch();
if(!empty($result) && password_verify($password, $result['passhash']))
What can I try next?
Single quotes prevent variable interpolation, so this encodes the literal string $password as the password:
$hash = password_hash('$password', PASSWORD_DEFAULT);
Just use the variable directly:
$hash = password_hash($password, PASSWORD_DEFAULT);
I am having issues getting some simple (or it seems simple) coding to cooperate. I've tried stripping it completely and typing everything out. Here is the code:
<?php
session_start();
if(isset($_POST['login'])) {
$username = trim($_POST['username']);
$password = md5(trim($_POST['password']));
include('includes/admin.php');
$sql = "SELECT * FROM users WHERE username='$username' AND password='$password'";
$result = mysqli_query($con, $sql);
if(mysqli_num_rows($result) == 0) {
echo '<p>Incorrect login.<br>Return to Login Page</p>';
} else {
$_SESSION['user'] = $username;
echo '<p>Login successful.<br>Go to Admin Page</p>';
}
}
?>
The goal is to have it redirect to the login page if unsuccessful and to redirect to another admin page if successful. I keep getting the "Incorrect Login" error, even when I type in the correct username and password.
Side Note: I know to redirect, I need to use header('Location: link.php'), it is not included for testing purposes.
If you didn't save your password as MD5 hash in your database you will never match it, cause in the line above you hash the password via MD5 before using in the query.
MD5 isn't secure! Use the PHP internal functions (password_hash(), password_verify()) to create and check passwords!
Use prepared statements!
Example code:
<?php
// Save a new user password in DB
$username = 'Max User';
$password = 'My_Secr3t_Pa5sw0rd';
$passwordHash = password_hash($password, PASSWORD_BCRYPT);
$stmt = $mysqli->prepare("INSERT INTO `users` (`username`, `password`) VALUES(?, ?)");
$stmt->bind_param("ss", $username, $passwordHash);
$stmt->execute();
// Check user password
$stmt = $mysqli->prepare("SELECT `password` FROM `users` WHERE `username`=?");
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
if (password_verify($password, $row['password']) {
echo "Password correct";
} else {
echo "Password incorrect!";
}
?>
I would like to verify my stored hashed passwords with the inputs that the users insert.
What theory says...
After read about the mechanism of password_hash and password_verify, I realized that, theoretically, the string that is inserted will be compared with a hash, which, at least in my case, is stored in the site db.
What is happening to me...
I register my users with password_hash and then to verify the login I use password_verify. If I am good and the code is right, this function should verify the input of the user (even if it's plain text(?) ) with the stored hash.
Let's see the code:
Registration code:
$passwordHash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 12));
Note: There is more code but I guess that this is the most important part so I decided to paste only this part.
Login code:
<?php
//controller!
require "../model/backend.php";
$username = $_POST['user'];
$password = $_POST['password'];
$dbcom = new dbInteraction;
$dbcom->admlog($username, $password);
$dbcom->conclose();
?>
Verification code:
$this->username = $username;
$this->password = $password;
//$this->pdo = $pdo;
//$adm = 1;
$myquery = 'SELECT username, password, isadmin FROM users WHERE username = :username';// AND password = :password';
$stmt = $this->pdo->prepare($myquery);
$stmt->bindParam(':username', $username, PDO::PARAM_STR);
$stmt->execute();
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if($user === false){
die('1Incorrect username / password combination!');
} else{
//Compare the passwords.
$dbpass = $user['password'];
echo $dbpass;
echo '<br>bd<br>input<br>';
echo $password;
$validPassword = password_verify($dbpass, $password);
echo '<br>debug <br>';
echo 'pre pass:<br>';
echo $validPassword;
if($validPassword){
//Provide the user with a login session.
$_SESSION['user_id'] = $user['username'];
$_SESSION['logged_in'] = time();
//header('Location: home.php');
exit;
}else{
die('<br>no pass--Incorrect username / password combination!');
}
}
Do I have some theoretical base problem in my code or it's just bad coded? I'm still trying to realize.
Thank you very much.
The problem was in the order of password_verify params.
It should be like $validPassword = password_verify($password, $dbpass);
or in generic words:
$validPassword = password_verify('String to verify', 'Saved password');
Special thanks to #JonStirling
I am using password_hash to store passwords in a MySQL database field of type VARCHAR(255). When I try to login the user and verify credentials, the password_verify function always returns false.
Here is the code excerpt that stores the password in the MySQL database:
$password_hash = password_hash($password, PASSWORD_DEFAULT);
// Generate API Key
$api_key = $this->generateApiKey();
// Insert Query
$stmt = $this->conn->prepare("INSERT INTO user(email, password, name, api_key, status) values(?, ?, ?, ?, 1)");
$stmt->bind_param("ssss", $email, $password_hash, $name, $api_key);
$result = $stmt->execute();
$stmt->close();
And the piece of code that checks the password:
// Query user by email
$stmt = $this->conn->prepare("SELECT password FROM user WHERE email = ?");
$stmt->bind_param("s", $email);
$stmt->execute();
$stmt->bind_result($password_hash);
$stmt->store_result();
if ($stmt->num_rows > 0) {
// Found user with that email address
// Now verify the password
$stmt->fetch();
$stmt->close();
if (password_verify($password, $password_hash)) {
// User password is correct
return TRUE;
Then I wrote this test code and grabbed the data straight from the MySQL field and it still fails. When I create the password_hash in the same file ($hash2 in the file below) - then the password verifies correctly.
$password = 'pass1234567890';
$hash = '$2y$10$JLP/pPei6RYRdUmoH8H5RO7iJyImOtrBLsrRRfq3XpeqNE3lQ/l7O';
$hash2 = password_hash($password, PASSWORD_DEFAULT);
echo $hash . " - " . strlen($hash);
echo "<br />";
echo $hash2 . " - " . strlen($hash2);
echo "<br />";
if (password_verify($password, $hash)) {
echo "Password Valid!";
} else {
echo "Password invalid!";
}
echo "<br /><br />";
if (password_verify($password, $hash2)) {
echo "Password 2 Valid!";
} else {
echo "Password 2 invalid!";
}
This proves that something is wrong with your hash
<?php
// See the password_hash() example to see where this came from.
$password = 'pass1234567890';
$hash = '$2y$10$JLP/pPei6RYRdUmoH8H5RO7iJyImOtrBLsrRRfq3XpeqNE3lQ/l7O';
$hash2 = '$2y$10$gMJKYZUc1FKSZBnsONxLOebOHj.uuEWSiCP0jo4Zv0iAHBz6iz.NG';
if (password_verify('pass1234567890', $hash)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}
echo "<br>";
if (password_verify('pass1234567890', $hash2)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}
Screenshot
In my case the probme was that I stored the database connection query in another file which included the same variable that I used for fetching current password, so what happened was that first I assigned a variable "password" to current password and then included my connection query file which had the same variable "password" therefore what happened was that, "password" variable of signup form was reassigned by "password" variable of connection query, and that's why it actually hashed another password. So by changing the variable name this problem was solved.
Here is my code for reference,
signup.php
$email = $_POST["email"];
$password = $_POST["password"];
include 'partials/php/_dbconnect.php';
$passwordHash = password_hash($passwd, PASSWORD_DEFAULT);
_dbconnect.php
<?php
$server = "localhost";
$username = "root";
$password = "";
$database = "demo";
$connectionquery = mysqli_connect($server, $username, $password, $database);
?>
which I changed to;
$email = $_POST["email"];
$passwd = $_POST["password"];
include 'partials/php/_dbconnect.php';
$passwordHash = password_hash($passwd, PASSWORD_DEFAULT);
password_verify($password,trim($password_hash)))
While I am unsure if it happened when the hash was stored or during retrieval, the password_hash had a space at the end. Trimming the hash before feeding it to password_verify fixed the issue for me.
Just make a variable for if(password_verify($pass_input, $pass_db))
where $pass_input is the value given from the textified form and $pass_db is the value stored in mysql (hashed)
Like this:
$verif_pass = (password_verify($pass_input, $pass_db));
if($verif_pass){echo "TRUE"} else {echo "FALSE";}
and just modify TRUE/FALSE as you want.
I have a problem with my code. Or rather don't know how to implement what I would like to have.
I would like; Also in this code, check if the username have a 1 in active column. and if so the proceed to login protected page else return to login page.
<?php
session_start();
function validateUser(){
session_regenerate_id ();
$_SESSION['valid'] = 1;
$_SESSION['username'] = $username;
}
$username = $_POST['username'];
$password = > $_POST['password'];
require('config.inc.php');
$db = new PDO("mysql:host=$dbhost;dbname=$dbname",$dbuser,$dbpass);
$stmt = $db->prepare("SELECT password_hash FROM users WHERE username =:username");
$stmt->bindParam(':username', $username, PDO::PARAM_STR,32);
$stmt->execute(); $result = $stmt->fetch(PDO::FETCH_ASSOC);
$db=null;
$dbhash = $result['password_hash'];
if ($dbhash == crypt($password, $dbhash)){
validateUser();
header('Location: ../main.php');
}else{
header('Location: ../index.php?invalidcreds=1');
die();
}
?>
So what you guys think? I have tried everything but can't get it to work.
Also I would like to have a admin column no/0 or yes/1 so I can protect certain links or text in my page. But first thing first.
You can add an is_active column in your db then use:
SELECT is_active, password_hash FROM users where username=:username
In your php just use:
if($result['is_active'])
{
//Send to restricted login
}
else
{
//Send to normal login
}
Also, like I said in a comment, you have a stray > when you initialize your password variable. It may be a reason why your code isn't working.
Okay so this is the code and it work perfect. And the > was just a typo sorry. Thanks Bun for your super easy code.
Does this look okay? Or just plain wrong. I'm a bit unsure of the if code or is this the way to go!?
<?php
session_start();
function validateUser(){
session_regenerate_id (); //this is a security measure
$_SESSION['valid'] = 1;
$_SESSION['username'] = $username;
}
$username = $_POST['username'];
$password = $_POST['password'];
require('config.inc.php');
$db = new PDO("mysql:host=$dbhost;dbname=$dbname",$dbuser,$dbpass);
$stmt = $db->prepare("SELECT active, password_hash FROM users WHERE username = :username");
$stmt->bindParam(':username', $username, PDO::PARAM_STR, 32);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$db =null;
if($result['active']){
$dbhash = $result['password_hash'];
if ($dbhash == crypt($password, $dbhash))
validateUser();
header('Location: ../main.php');
}
else{
header('Location: ../index.php?invalidcreds=1');
die();
}
?>
But now if I would like to do a admin column too and try to implement this here, how would I do this? I know there needs to be added perhaps a bit more code in other places also. Nothing pretty or advanced. It's just a simple login so. Any advice where I should direct my eyes at, private/public classes (I've tried this but I got lost in the code totaly)