DEV Community

Elijah Emmanuel
Elijah Emmanuel

Posted on

How Can i create a Secure SignIn Portal In PHP after Using Password Hash on SignUp Page.

Please fellow Devs, i just created a Signup(Registration) Portal in PHP using password Hash to store my password in the Database, but i cannot Login to the welcome page because the password passed from the login page is not the same as the Hashed password in the database.
Here is the code below:
someone should please tell me whats wrong, thanks.

FORM
<?php
include_once('../public/header.php');
include('../validate/login.php');
?>

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="../public/styles/style.css">
    <title>student login</title>
</head>


<body>

    <div class="container ml-lg-5 mr-lg-5">
        <div class="row ml-lg-5 mr-lg-5 p-lg-5">
            <div class="col ml-lg-5 mr-lg-5 p-lg-5 shadow">
                <form action="" method="POST">
                    <div class="text-danger"><?php echo $err_msg ?></div>
                    <label for="regno">Reg No</label>
                    <input type="text" name="regno" class="form-control">
                    <div class="text-danger"><?php echo $regno_err ?></div>

                    <label for="password">Password</label>
                    <input type="password" name="password" class="form-control">
                    <div class="text-danger"><?php echo $password_err ?></div>

                    <input type="submit" value="LOGIN" class="btn btn-outline-primary">
                </form>
            </div>
        </div>
    </div>


</body>

</html>
Enter fullscreen mode Exit fullscreen mode
FORM VALIDATION CODE
<?php
$err_msg = $regno_err= $password_err= "";
if($_SERVER["REQUEST_METHOD"] == "POST"){

    if ( !isset($_POST['regno'], $_POST['password']) ) {
        // Could not get the data that should have been sent.
        $err_msg='Please fill both the username and password fields!';
    };

    if(empty(trim($_POST['regno']))){
    $regno_err="please fill in regno";
    }elseif ($stmt = $conn->prepare('SELECT * FROM user WHERE regno = ?')) {
        // Bind parameters (s = string, i = int, b = blob, etc), in our case the username is a string so we use "s"
        $stmt->bind_param('s', $_POST['regno']);
        $stmt->execute();
        // Store the result so we can check if the account exists in the database.
        $stmt->store_result();

        if($stmt->num_rows == "false"){
            $regno_err= "user does not exist";
        }else{
            $regno=$_POST['regno'];

            $sql = "SELECT * From user WHERE regno = '{$regno}' ";
            $query = mysqli_query($conn, $sql);

            if(!$query){
                die('unable to query'.$conn->error);
            }


             while($row = mysqli_fetch_array($query)) {
                    $id            = $row['id'];
                    $username     = $row['username'];
                    $regno_in      =$row['regno'];
                    $email         = $row['email'];
                    $department   = $row['department'];
                    $pass_word     = $row['password'];
                }



            $password=password_verify($pass_word,$_POST['password']);
            if($regno_in ==$regno && $pass_word == $password){
                echo "you are welcome";
                $_SESSION['password'] = $pass_word;

                echo "your email is:".$_SESSION['password'];
            }else{
                echo "password does not match db";
            }

            }

        $stmt->close(); 
        }
    }$conn->close();
?>
Enter fullscreen mode Exit fullscreen mode

Latest comments (5)

Collapse
 
grahamthedev profile image
GrahamTheDev • Edited

Quick Tip - Add the #help tag to posts where you need a hand with things, that way people who are looking to help will be on hand!

Possible cause

On the line $password=password_verify($pass_word,$_POST['password']);

What you are doing is instructing the system to check that the post variable "password" should be hashed and then check if it matches $pass_word - your hashed variable.

password_verify returns a boolean (true / false) which (hopefully) should return true in this instance.

In the line below that you try and compare $password (true or false) to $pass_word (A hashed password value).

So if you change the line to
if($regno_in ==$regno && $password == true){

You should get a successful login (assuming you have done everything else correctly as in your question you said the hashes did not match, but I cannot tell if that is from something you echoed out or just because you couldn't log in).

Couple of observations just to be aware of

Just a few things to consider as you are learning so you don't develop bad habits which you later have to unlearn.

  1. Be careful with queries and user input - you used bound variables in your first query so that should be pretty safe (but you should still sanitise it - rule one is never trust user input!) but in your second query you just pass the $_POST parameter straight to the query which is dangerous as a user can send anything they want in that $_POST parameter. Also you don't need to query twice, you already have the query results from your first query as it is identical so remove the second query.

  2. Possible issue with duplicate entries - you should check that your query only returns 1 result before grabbing the information and return an error if you return more than one row. If 2 people had the same regNo due to a mistake you would always grab the second persons regNo because you use a while loop and overwrite the values. Or you can just make the regNo field unique entries only (which you may already have done) to avoid this.

  3. "user does not exist" allows people to guess regNo - It is not a good practice to have "user does not exist" echoed out - that may just be for testing purposes (which is fine), but in production that lets an attacker know when they have successfully guessed a correct regNo so they can brute force attack more easily. Instead just return "incorrect username or password" in production.

  4. Don't store the password hash in a session - Finally I would recommend not storing the password itself as a session variable, it could open up an attack vector (although this is not a huge concern compared to the other things mentioned as session variables are pretty secure). As sessions are per user and managed by the server you can just save that they are authenticated.

Collapse
 
vinhpedro profile image
Elijah Emmanuel

thanks alot sir, your advice helped me alot.
am grateful, i will try my best to implement all that you have recommended me to adhere to.

Collapse
 
rvxlab profile image
RVxLab • Edited

In addition, this line is vulnerable to an SQL Injection:

$sql = "SELECT * From user WHERE regno = '{$regno}' ";
Enter fullscreen mode Exit fullscreen mode
Collapse
 
grahamthedev profile image
GrahamTheDev

That was the bit I meant with point 1 but it obviously wasn't clear, thanks for pointing it out! ❤

Thread Thread
 
vinhpedro profile image
Elijah Emmanuel

thank you all, your advice really helped me