Why PHP authentication works incorrect? - php

I am newbie in PHP.
I have simple authentication script. It works incorrect: user "test" (100% existing in table in DB) can not pass auth (error text - "User is not found!").
Use PHP7, MySQL, connection method is PDO.
Need some help please.
$data = $_POST;
// check if button is pressed
if (isset($data['enter-auth'])) {
// check fileds
$errors = array();
if (trim($data['login_auth']) == '' ) {
$errors[] = 'Enter login';
}
if (($data['password_auth']) == '' ) {
$errors[] = 'Enter password';
}
// If all fields are filled, save user's data in vars
$login = $data['login_auth'];
$password = password_hash($data['password_auth'], PASSWORD_DEFAULT);
// ... and look in table
try {
if (empty($errors)) {
// Check if login and password exists in table
$stmt = $pdo->prepare("SELECT count(*) FROM users WHERE login=? AND password=?");
$stmt->execute([$login, $password]);
$count = $stmt->fetchColumn();
// If login and pwd found in table counter will be > 0, so ...
if ($count > 0) {
// ... then we can check if password is correct
if (password_verify($data['password_auth'], $password)) {
// if entered and stored passwords match, user is welcome
$_SESSION['auth_name'] = $data['login_auth'];
echo '<div style="color: green;">Welcome, '.$_SESSION['auth_name'].';
echo 'Exit';
header('Location: /a/index.php');
} else {
$errors[] = 'Password is incorrect';
echo '<p id="message">Wrong password!</p>';
}
} else {
$errors[] = 'User not found';
echo '<p id="message">User is not found!</p>';
}
} else {
echo '<div style="color: red;">'.array_shift($errors).'</div>';
}
} catch(PDOException $e) {
echo $e->getMessage();
}
// close condition check if button is pressed
}
Notes:
I tryed debugging this script using var_dump.
If I use fetchAll() when searching in table, any entered ldin is accepted (even if there is no such user).
Used try/catch construction with debug aim, I've heard that in production it is deprecated because of security reason.

Found mistakes, rewrote the code according to https://phpdelusions.net/pdo_examples/password_hash
So, correct fragment is:
try {
if (empty($errors)) {
$stmt = $pdo->prepare("SELECT login, password FROM users WHERE login=?");
$stmt->execute([$login]);
$user = $stmt->fetch();
if ($user && password_verify($data['password_auth'], $user['password'])) {
$_SESSION['auth_name'] = $data['login_auth'];
echo '<div style="color: green;">Welcome, '.$_SESSION['auth_name'].';
echo 'Exit';
header('Location: /a/index.php');
} else {
$errors[] = 'Login or password error';
echo '<p id="message-auth">Login or password is incorrect!</p>';
}
} else {
echo '<div style="color: red;">'.array_shift($errors).'</div>';
}
} catch(PDOException $e) {
echo $e->getMessage();
}

Related

Add password hash in pdo login

I cannot manage to add a password hash in my sign up code. I am new to PDO and I tried different things but cannot manage to make a working registration with password hash!
Can someone help me? Here my code:
<?php
include('header.php');
// Check if logged in
if($user->is_loggedin()!="")
{
$user->redirect('home.php');
}
$error='';
if(isset($_POST['btn-signup']))
{
// trim empty spaces on inserted data
$uname = trim($_POST['name']);
$umail = trim($_POST['email']);
$upass = trim($_POST['password']);
$repeat_password = trim($_POST['repeat_password']);
// validate username
if($uname=="") {
$error.= "provide username ! <br>";
}
// validate e-mail
else if($umail=="") {
$error.= "provide email id ! <br>";
}
else if(!filter_var($umail, FILTER_VALIDATE_EMAIL)) {
$error.= 'Please enter a valid email address ! <br>';
}
// validate password
else if($upass=="") {
$error.= "provide password ! <br>";
}
else if(strlen($upass) < 6){
$error.= "Password must be atleast 6 characters <br>";
}
else if( $upass!=$repeat_password){
$error.= "Password Does Not Match <br>";
}
else
{
// check if email is already taken
try
{
// prepare statement
$stmt = $DB_con->prepare("SELECT email FROM users WHERE email=:umail");
$stmt->execute(array(':umail'=>$umail));
$row=$stmt->fetch(PDO::FETCH_ASSOC);
if($row['email']==$umail) {
$error.= "sorry email id already taken ! <br>";
}
// if everything is validated save data
else
{
if($user->register($uname,$umail,$upass))
{
$_SESSION['success']='You have been Registered Successfully';
$user->redirect('login.php');
}
}
}
// set the error mode
catch(PDOException $e)
{
echo $e->getMessage();
}
}
}
And here the class "user"
<?php
class User
{
private $db;
function __construct($DB_con)
{
$this->db = $DB_con;
}
// get user by passed in data
public function register($uname,$umail,$upass)
{
try
{
// $new_password = password_hash($upass, PASSWORD_DEFAULT); // Creates a password hash;
$new_password = $upass;
// prepared statement
$stmt = $this->db->prepare("INSERT INTO users(name,email,password,user_type)
VALUES(:uname, :umail, :upass,'user')");
// bind param with values
$stmt->bindparam(":uname", $uname);
$stmt->bindparam(":umail", $umail);
$stmt->bindparam(":upass", $new_password);
$stmt->execute();
return $stmt;
}
// set the error mode
catch(PDOException $e)
{
echo $e->getMessage();
}
}
public function login($umail,$upass)
{
try
{
// prepare statement
$stmt = $this->db->prepare("SELECT * FROM users WHERE email=:umail LIMIT 1");
$stmt->execute(array(':umail'=>$umail));
$userRow=$stmt->fetch(PDO::FETCH_ASSOC);
if($stmt->rowCount() > 0)
{
if($upass==$userRow['password'])
{
$_SESSION['user_id'] = $userRow['id'];
$_SESSION['name'] = $userRow['name'];
$_SESSION['role'] = $userRow['user_type'];
return true;
}
else
{
return false;
}
}
}
// set the error mode
catch(PDOException $e)
{
echo $e->getMessage();
}
}
public function is_loggedin()
{
if(isset($_SESSION['user_id']))
{
return true;
}
}
public function redirect($url)
{
header("Location: $url");
}
public function logout()
{
session_destroy();
unset($_SESSION['user_id']);
return true;
}
}
?>
In the commented line in the class script you can see a try I made, it hashed the password but then the pw wouldn't be saved in my sql database.
Sorry if the question is stupid but I am learning :)
I want to point out few things first:
Do not use trim to users password. Unless if you want to restrict your users from entering spaces to their passwords.
Use === when doing comparison. It is better because it checks datatype at the same time. For example if you have "2" and 2 and you use == operator it equals. It is good practice to check datatype because it prevents alot error from happening.
As what comes to problem that you wanted to get answer
You don't use password_hash function at any point. You only assign raw password to variable and assign this variable to bind_param function.
$new_password = $upass;
Should be instead
$new_password = password_hash($upass, PASSWORD_DEFAULT);
However i do not recommend using PASSWORD_DEFAULT as you could get more secure hash by using PASSWORD_ARGON2I. You can check more information about password_hash from PHP manual.
And to help you out even more: when you want to verify that user enters correct password at login you need to use password_verify(). It compares hash to password that user entered and if it is correct this function will return true.
Example:
$login_status = password_verify($_POST['password'], $user_password_from_database);
if($login_status === true) {//set session etc...}
You can read more about password_verify here

PHP displaying error code once

When a user clicks login, "Wrong Email Or Password" Is displayed for each user that is in Database Array. Could someone point me in the right direction to Only Display Error code once if user input wrong email/password?
I'm Using Flintstone to store Users.
if (isset($_POST['login'])) {
$TempEmail = strtolower($_POST['email']);
$TempPass = $_POST['password'];
// Get Keys From DB;
$keys = $users->getKeys();
// Check If DB is Empty
if (!empty($keys)) {
foreach ($keys as $key) {
$user = $users->get($key);
$email = strtolower($user['Email']);
$password = $user['Password'];
$hash = password_verify($TempPass, $password);
try {
if (($TempEmail === $email) && ($hash === true))
{
$_SESSION['use']=$email;
// On Successful Login redirects to home page
header("Location:/home/");
}
else
{
echo "Wrong Email Or Password";
//break;
}
} catch (Exception $e) {
return $e->getMessage();
}
}
} else {
echo "DB Is Empty";
exit;
}
}
Simply move echo "Wrong Email Or Password" right after the foreach-loop instead of inside it. If the email is found and the password matches, the user will still be redirected before the code reaches that point.
foreach ($keys as $key) {
// Your current code, minus the echo.
}
// This is after the foreach and will only be executed if there were
// no match for the email and password.
echo "Wrong Email Or Password";
Just remember to add an exit; after your header('Location:....'); to stop PHP from executing anything more.
The foreach loop goes through all the $keys, hence it echoes "Wrong Email Or Password" for every wrong key.
Save the outcome of a successfull query in a variable i.e. $success = false. If the correct login was found, set it to true. After the foreach loop you can write
if(!$success){echo "Wrong password"};
I think this is more user-friendly:
$login = false;
foreach ($keys as $key) {
$user = $users->get($key);
$email = strtolower($user['Email']);
$password = $user['Password'];
$hash = password_verify($TempPass, $password);
try {
if ($TempEmail === $email) {
if ($hash === true) {
$login = true;
$_SESSION['use'] = $email;
// On Successful Login redirects to home page
header("Location:/home/");
} else {
break;
}
}
} catch (Exception $e) {
return $e->getMessage();
}
}
if (!$login) {
echo "Wrong Email Or Password";
}

How to choose page using if else in mysql_num_rows

Please help me I want my program to choose a site if it has not yet username then it will proceed it to ch_uname.php. Then if the login credentials have already username then it will be preceded to index_profile.php. Thank you in advance.
if(mysql_num_rows($runcreds)> 0 ) //checking log in forms
{
if(mysql_num_rows($run_uname)>=1 ) //if username has already avalaible(proceed)
{
$_SESSION['Email_add']=$email;
echo "<script>window.open('modules/index_profile.php','_self')</script>";
}
if(mysql_num_rows($run_uname)<1)//choouse username if has not yet username
{
$_SESSION['Email_add']=$email;
echo "<script>window.open('forms/ch_uname.php','_self')</script>";
//modules/index_profile.php
}
}
else
{
echo "<script>alert('Admin details are incorrect!')</script>";
}
}
Here is a basic demonstration (using a PDO connection) of what I think you are looking for? I am assuming some stuff here because you don't give enough info before your code snippet:
session_start();
// I will use PDO because I cannot bring myself to use mysql_ in this demonstration
// Initiate connection (assigning credentials assumed)
$con = new PDO("mysql:host=$mysqlDB;dbname=$mysqlTable", $mysqlUser, $mysqlPass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_SILENT));
if(isset($_POST['login'])) {
$username = trim($_POST['username']);
// Stop if empty
if(empty($username)) {
// You can echo or assign to a variable to echo down the page
echo 'Username cannot be empty';
return;
}
// Set up prepared statement
$query = $con->prepare("select Email_add,password from `users` where username = :username");
$query->execute(array(":username"=>$username));
// Loop through returned
while($row = $query->fetch(PDO::FETCH_ASSOC)) {
$result[] = $row;
}
// If the loop comes up blank, assign false (0)
$result = (isset($result) && !empty($result))? $result:0;
// If username exists
if($result != 0) {
// I am assuming you have some form of super secure hash method for passwords...
$password = bcrypt($_POST['password']);
// If passwords match, create session
if($result[0]['password'] == $password) {
$_SESSION['Email_add'] = $result[0]['Email_add'];
// You probably don't need javascript to redirect
header('Location: modules/index_profile.php');
exit;
}
else {
// Password doesn't match
// You can echo or assign to a variable to echo down the page
echo 'Invalid Username/Password';
}
}
// This would mean the username doesn't exist
else {
header('Location: forms/ch_uname.php');
exit;
}
}

PHP crypt validation with PDO prepared statement Error

and sorry for the [duplicate]. i spent a day, not able to find a solution. I am having a problem with crypt (validation), here is my code:
function generateHash($password, $round=10){
$salt=substr(base64_encode(openssl_random_pseudo_bytes(17)),0,22);
$salt=str_replace("+",".",$salt);
$param='$'.implode('$',array(
"2y",
str_pad($round,2,"0",STR_PAD_LEFT),
$salt
)
);
return crypt($password,$param);
}
//NOW I INSERT HASH TO DB
$input = "abc";
$hashed = generateHash($input);
$createAccount=$db->prepare("INSERT INTO account ....
':secret' => $hashed;
.....)); // Until here, no problem, $hashed can be inserted correctely into my db (password, Varchar (64)
Now after registration, user likes to login, here is the problem. First, i'm checking, to see, if i did well the function
$input = "abc";
$forCheck = "abc";
$hashedHash = generateHash($input);
if (crypt($forCheck, $hashedHash) == $hashedHash) {
echo "MATCH";
}else {
echo "NOT MATCH";
}
// OUTPUT: "MATCH"
The problem is here:
$check=$db->prepare("SELECT id, password FROM account WHERE email = :email ");
$check->execute(array(
':email' => $user
)
);
if ($check->rowCount() <= 0) {
echo "You are not registered";
}else {
$sRow=$check->fetchAll(PDO::FETCH_ASSOC);
foreach ($sRow as $row) {
$hashedHash = generateHash($row['password']);
if (crypt($input, $hashedHash) == $hashedHash) {
echo "Passwords Matched";
}else {
echo "Passwords did not match";
}
}
}
// OUTPUT: "Passwords did not match"
Any help please ?
The problem is here...
$hashedHash = generateHash($row['password']);
You aren't storing a plain text password so why would you pass the hash through generateHash again? Should simply be
if (crypt($input, $row['password']) == $row['password'])
I'd also take this opportunity to clean up your query logic. For one thing, PDOStatement::rowCount should not be relied upon.
$check = $db->prepare('SELECT id, password FROM account WHERE email = :email LIMIT 1');
$check->execute([':email' => $user]);
if ($row = $check->fetch(PDO::FETCH_ASSOC)) {
if (crypt($input, $row['password']) == $row['password']) {
echo 'Passwords Matched';
} else {
echo 'Password did not match';
}
} else {
echo 'You are not registered';
}

Log in returns blank for incorrect password?

I have been using a tutorial for a registration and log in page. Everything is perfect except when a user inputs an incorrect password.
If no password is entered then the stated error is displayed fine.
If the correct password is entered it logs them in.
If the incorrect password is entered it goes to a blank page?!
I want an incorrect password to display a message just like when the wrong username is entered. I've included my entire login.php code:
include('db.php');
if(!isset($_POST['login'])) {
include('form.php');
} else {
if(isset($_POST['user'])&&$_POST['user']==""||!isset($_POST['user'])) {
$error[] = "Username Field can't be left blank";
$usererror = "1";
}
if(!isset($usererror)) {
$user = mysql_real_escape_string($_POST['user']);
$sql = "SELECT * FROM users WHERE user = '$user'";
if(mysql_num_rows(mysql_query($sql))=="0") {
$error[] = "Can't find a user with this username";
}
}
if(isset($_POST['pass'])&&$_POST['pass']==""||!isset($_POST['pass'])) {
$error[] = "password Field can't be left blank";
}
if(isset($error)) {
if(is_array($error)) {
echo "<div class=\"error\"><span>please check the errors and refill the form<span><br/>";
foreach ($error as $ers) {
echo "<span>".$ers."</span><br/>";
}
echo "</div>";
include('form.php');
}
}
if(!isset($error)) {
$suser=mysql_real_escape_string($_POST['user']);
$spass=md5($_POST['pass']);//for secure passwords
$find = "SELECT * FROM users WHERE user = '$suser' AND password = '$spass'";
if(mysql_num_rows(mysql_query($find))=="1"or die(mysql_error())) {
session_start();
$_SESSION['username'] = $suser;
header("Location: loggedin.php");
} else {
echo "<div class=\"warning\"><span>Some Error occured durring processing your data</div>";
}
}
}
if(mysql_num_rows(mysql_query($find))=="1"or die(mysql_error())){
If wrong password is entered, mysql_num_rows(mysql_query($find)) is 0 so it results in die(mysql_error()). But since there is no mysql_error(), you see a blank page.
Try this
$result = mysql_query($find) or die(mysql_error());
if (mysql_num_rows($result) == 1) {
// proceed
} else {
// authentication failed
}
EDIT: This is just for illustration purpose only. Use MySQLi or PDO when dealing with MySQL.
The code is little bit confusing for me, consider using this code.
<?php
include('db.php');
if(isset($_POST['login'])) {
$username = mysql_real_escape_string($_POST['user']);
$password = md5($_POST['pass']);
if(empty($username) || empty($password)) {
echo "Empty username or password.";
} else {
mysql_query("SELECT * FROM `users` WHERE `user` = '$user' AND `password.md5` = '$password'");
if(mysql_num_rows() == 1) {
// login successfull
session_start();
$_SESSION['username'] = $username;
header("Location: loggedin.php");
} else {
echo "Invalid username or password.";
}
}
} else {
include ('form.php');
}
?>

Categories