Why Am I Failing To Log in With The Password_Verify Function ?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • bits2017
    New Member
    • Jun 2017
    • 39

    Why Am I Failing To Log in With The Password_Verify Function ?

    Php Programmers,

    Why is the password_verify failing on this script ?
    I do not think I got it wrong! Do you ?
    You will see, it fails to log you in to your account with the correct Username/Email and Password.
    Do check the script on your end in Xampp/Wamp.

    Cheers.
    Code:
    <?php
     
    /*
    ERROR HANDLING
    */
    declare(strict_types=1);
    ini_set('display_errors', '1');
    ini_set('display_startup_errors', '1');
    error_reporting(E_ALL);
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
     
    include 'config.php';
     
    // check if user is already logged in
    if (is_logged() === true) 
    {
    	//Redirect user to homepage page after 5 seconds.
    	header("refresh:2;url=home.php");
    	exit; //
    }
    
    
    if ($_SERVER['REQUEST_METHOD'] == "POST")
    { 
    	if (isset($_POST["login_username_or_email"]) && isset($_POST["login_password"]))
    	{
    		$username_or_email = trim($_POST["login_username_or_email"]); //
    		$password = $_POST["login_password"];
    		$hashed_password = password_hash($password, PASSWORD_DEFAULT);
             
    		//Select Username or Email to check against Mysql DB if they are already registered or not.
    		$stmt = mysqli_stmt_init($conn);
    		
            if(strpos("$username_or_email", "@") === true)
    		{
    			$email = $username_or_email;
    			$username = "";
    			
    			$query = "SELECT ids, usernames, passwords, emails, accounts_activations_statuses FROM users WHERE emails = ?";
    			// i = integer; s = string; d = double; b = blob.
    			mysqli_stmt_init($stmt);
    			$stmt = mysqli_prepare($conn, $query);			
    			mysqli_stmt_bind_param($stmt, 's', $email);
    			mysqli_stmt_execute($stmt);
    		    $result = mysqli_stmt_bind_result($stmt, $db_id, $db_username, $db_password, $db_email, $db_account_activation_status); // ... this line. But not both.
    		}
    		else
    		{
    			$username = $username_or_email;
    			$email = "";
    			$query = "SELECT ids, usernames, passwords, emails, accounts_activations_statuses FROM users WHERE usernames = ?";
    			$stmt = mysqli_prepare($conn, $query);
    			mysqli_stmt_bind_param($stmt, 's', $username);
    			mysqli_stmt_execute($stmt);
    			$result = mysqli_stmt_bind_result($stmt, $db_id, $db_username, $db_password, $db_email, $db_account_activation_status); // ... this line. But not both.#
    		}       	
    		
    		//QUESTION: Which one of the following 3 to do and why that one over the other 2 ?
    		$row = mysqli_stmt_fetch($stmt);
    		//$row = mysqli_fetch_array($query, MYSQLI_ASSOC);
    		//$row = mysqli_fetch_array($result, MYSQLI_ASSOC);
    		
    		mysqli_stmt_close($stmt);
    		
    		printf("%s (%s)\n",$row["usernames"],$row["passwords"]);
    		echo "var_dump(row)";var_dump($row);?><br><?php //On test, this showing as: () bool(true);
    		echo "var_dump(result)";var_dump($result)?><br><?php //On test, this showing as: () bool(true);
    		
    		if ($result == false)
    		{
    			echo "Incorrect User Credentials 1 - (query result == FALSE on LINE 79! )!<br>";
    			echo "Id from db: $db_id<br>";
    			echo "Email from db: $db_email<br>";
    			echo "Username from db: $db_username<br>";
    			echo "Hash from db: $db_password<br>";
    			echo "Account Activation Status from db: $db_account_activation_status<br>";
    			exit(); 
    		}
    		elseif ($row['accounts_activations_statuses'] == '0')
    		{
    			{
    				echo "You have not activated your account yet! Check your email for instructions on how to activate it. 
    				Check your spam folder if you don't find an email from us.";
    				exit();
    			}
    		}
    		else
    		{
    			echo "Else got triggered on LINE 98! - (query result = TRUE)!<br>";//This ELSE is getting triggered on the test. That means $result = TRUE;
    			echo "Id from db: $db_id<br>";
    			echo "Email from db: $db_email<br>";
    			echo "Username from db: $db_username<br>";
    			echo "Hash from db: $db_password<br>";
    			echo "Account Activation Status from db: $db_account_activation_status<br>";
    		}
    		
    		if (password_verify($password, (string)$row['passwords']))
    		{
    			//If 'Remember Me' check box is checked then set the cookie. 
    			if(!empty($_POST["login_remember"])) // Either use this line ....
    			//if (isset($_POST['login_remember']) && $_post['login_remember'] == "on") // ...or this line. But not both!
    			{
    				setcookie("login_username", $username, time()+ (10*365*24*60*60));
    			}
    			else
    			{
    				//If Cookie is available then use it to auto log user into his/her account!
    				if (isset($_COOKIE['login_username']))
    				{
    					setcookie("login_username","","");
    				}
    			}
    			$_SESSION["user"] = $username;
    			header("location:home.php?user=$username");				
    		}
    		else
    		{
    			echo "Incorrect User Credentials 2! (Else got triggered on LINE 124. Stating: 'password_verify = FALSE');<br>";
    			echo "Id from db: $db_id<br>";
    			echo "Email from db: $db_email<br>";
    			echo "Username from db: $db_username<br>";
    			echo "Hash from db: $db_password<br>";
    			echo "Account Activation Status from db: $db_account_activation_status<br>";
    			exit();
    		}
    	}
    }
    	
    ?>
    
    <!DOCTYPE html>
    <html>
    <head>
    <title><?php $site_name?> Member Login Page</title>
      <meta charset="utf-8">
    </head>
    <body>
    <div class = "container">
    <form method="post" action="">
    <center><h3><?php $site_name ?> Member Login Form</h3></center>
    <div class="text-danger">
    <div class="form-group">
    <center><label>Username/Email:</label>
    <input type="text" placeholder="Enter Username" name="login_username_or_email" value="<?php if(isset($_COOKIE["login_username_or_email"])) echo $_COOKIE["login_username_or_email"]; ?>"</center>
    </div>
    <div class="form-group">
    <center><label>Password:</label>
    <input type="password" placeholder="Enter password" name="login_password" value="<?php if(isset($_COOKIE["login_password"])) echo $_COOKIE["login_password"]; ?>"></center>
    </div>
    <div class="form-group">
    <center><label>Remember Login Details:</label>
    <input type="checkbox" name="login_remember" /></center>
    </div>
    <div class="form-group">
    <center><input type="submit" name="login_submit" value="Login" class="button button-success" /></center>
    </div>
    <div class="form-group">
    <center><font color="red" size="3"><b>Forgot your password ?</b><br><a href="login_password_reset.php">Reset it here!</a></font></center>
    <center><font color="red" size="3"><b>Not registered ?</b><br><a href="register.php">Register here!</a></font></center>
    </form>
    </div>
    </body>
    </html>
    It fails to log me in with the correct password. Column name: passwords. And not "password" or "Password" or "Passwords" as some might suspect I done a typo in column name when I have not.
  • RonB
    Recognized Expert Contributor
    • Jun 2009
    • 589

    #2
    Start by fixing your formatting so that the code is readable. In doing so, you might find the problem.
    Last edited by RonB; Sep 18 '17, 03:25 PM.

    Comment

    • bits2017
      New Member
      • Jun 2017
      • 39

      #3
      How to fix the formatting ? I put the code inside:
      opening & closing "code" tags.

      Comment

      • RonB
        Recognized Expert Contributor
        • Jun 2009
        • 589

        #4
        Do not put multiple statements on 1 line.

        Put each statement on separate lines and add proper indentation.

        Comment

        • bits2017
          New Member
          • Jun 2017
          • 39

          #5
          Copied & pasted from Note Pad++ last time and things showed-up messy. But now neat. What do you think ?
          Anyway, if you know php then how-about replying to my original post ?

          Comment

          • RonB
            Recognized Expert Contributor
            • Jun 2009
            • 589

            #6
            I do work with php a little, only if I have to, but I'm not an expert in it.

            The password_verify function is not in the code you posted so I can't explain why it's failing.

            If you haven't already done so, you should add some debug print statements to verify that the vars hold the values you expect.

            When troubleshooting things like this, it's best to write a short but complete test script that that duplicates the problem. That makes it easier for others to help and in the course of creating the test script, you will often discover the cause of the problem.
            Last edited by RonB; Sep 19 '17, 02:36 PM.

            Comment

            • RonB
              Recognized Expert Contributor
              • Jun 2009
              • 589

              #7
              It's been awhile since I was last forced to use php and forgot that it had a password_verify (). I was thinking is was from your imported config.php script.

              I'll take another look at your script later when I have more free time.

              Comment

              • RonB
                Recognized Expert Contributor
                • Jun 2009
                • 589

                #8
                Code:
                if (password_verify($password, (string)$row['passwords']))
                Why do you have (string) in that conditional?

                Remove it and see if that helps.

                Comment

                • Rabbit
                  Recognized Expert MVP
                  • Jan 2007
                  • 12517

                  #9
                  Did you compare the hash stored in the database with the hash of the password submitted?

                  Comment

                  • bits2017
                    New Member
                    • Jun 2017
                    • 39

                    #10
                    RonB & Rabbit,

                    Remember this showed error:

                    Code:
                    if (password_verify($password, $row['passwords']))
                    Fatal error: Uncaught TypeError: password_verify () expects parameter 2 to be string, null given in C:\xampp\htdocs \e_id\login.php :77 Stack trace: #0 C:\xampp\htdocs \e_id\login.php (77): password_verify ('password', NULL) #1 {main} thrown in C:\xampp\htdocs \e_id\login.php on line 77

                    Therefore, I switched this:
                    password_verify ($password, $row['passwords']);
                    To this:
                    password_verify ($password, (string)$row['passwords']);

                    And this error is gone:
                    "Fatal error: Uncaught TypeError: password_verify () expects parameter 2 to be string, null given in C:\xampp\htdocs \e_id\login.php :77
                    Stack trace:
                    #0 C:\xampp\htdocs \e_id\login.php (77): password_verify ('password', NULL)
                    #1 {main} thrown in C:\xampp\htdocs \e_id\login.php on line 77".

                    But should the code really be like that by Type Casting the password_verify 2nd param ? Others reply: No!
                    However, no-one has managed to provide a proper solution yet which I have tested and found positive. I have been given 2 samples to test and so I will keep you guys updated. Saying all this, I do not want to simply rely on the 2 samples as they may not work. And so, do give your on professional inputs on this issue too.

                    AIM:
                    I am trying to create a Login system where the user can login to his account by either typing his Username or Email and Password. Like you do with your Youtube account.

                    As for why I did not query for the Password at the beginning alongside the Username and why I am querying for the Username/Email on the 1st attempt and Password on the 2nd attempt. Well if you read posts 13 & 17 (by Psycho) then you might understand why.

                    Infact, read the original post there first or you won't understand the full context of the discussion. Let me know if you agree or disagree with Psycho there. I've got feed-back now that it is bad advice and internet is full of it. But, I want your opinion here too.

                    I agree not all advice found on the internet is sound. I have found this true when Users at phpfreaks.com and maybe codingforums started pointing out that the sample codes from stackoverflow.c om are buggy.
                    Buggy codes found here:


                    Anyway, I started believing Psycho in phpfreaks.com (not sure if he is right or wrong but let's see what pros (you included) say in both this forum and others) and that is why my current code is structured to query the Username/Email & Password in 2 separate attempts after I failed to get it to query it in a single attempt after adding PREP STMTS.
                    I did manage it in a single attempt on the NON-PREP STMT once upon a time. But, when I started adding the PREP STMT the trouble started.
                    If you check the 1st post there then you will see an attempt was made to check for Username/Email & Password on 1st attempt but it failed. And so, my current code took the turn towards Pycho's advice to make the query in 2 separate attempts instead.
                    Finally, don't forget to give your professional opinion on how the code should be where on the 1st attempt the query checks if there is a Username/Email & Password match or not..
                    Anyone else are welcome too!

                    Once again, thanks!

                    Comment

                    • RonB
                      Recognized Expert Contributor
                      • Jun 2009
                      • 589

                      #11
                      Since I don't have a copy of your database, I can't actually run any tests. Looking at raw code will only get you so far and rarely is enough to do proper troubleshooting . Can you provide us with a dump of a test db that has a few test records?

                      The error message you're receiving suggests that $row['passwords'] is NULL. However, the line number it gives is not even close to where you call the password_verify () function, which leads me to believe that the error message didn't come from the code you posted.

                      Comment

                      • RonB
                        Recognized Expert Contributor
                        • Jun 2009
                        • 589

                        #12
                        I don't know how much experience you have in forums like this, but the best way to ask for help and receive a solution is to post a short but complete (self contained) test script that demonstrates the problem so that we can duplicate and troubleshoot the issue.

                        You should also post the errors and warnings that your posted code produces so that we can verify that it matches up with our results. And, if those messages differ from what you get from your actual full script, you should say so and post those messages.
                        Last edited by RonB; Sep 22 '17, 02:54 AM.

                        Comment

                        • bits2017
                          New Member
                          • Jun 2017
                          • 39

                          #13
                          RonB,

                          Thank you for your efforts. I try learning as much as I can from as manys forums I can without neglecting any.

                          It seems the issue was the "passwords" column size was too small (50 chars). Switching it to 255 should have made a difference but it did not in my test last night due to me not repopulating the column. Others in another forum suggested I repopulate and I read their suggestion just now and it is working after I repopulated it. Just sharing this knowledge on all forums I opened threads on this issue so it benefits other newbies too. I know this is nothing "learnable" for pros.


                          And so, this code is no longer getting the password_verify to false when I type the correct password.
                          Code:
                          Code:
                          <?php
                           
                          /*
                          ERROR HANDLING
                          */
                          declare(strict_types=1);
                          ini_set('display_errors', '1');
                          ini_set('display_startup_errors', '1');
                          error_reporting(E_ALL);
                          mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
                           
                          include 'config.php';
                           
                          // check if user is already logged in
                          if (is_logged() === true) 
                          {
                          	//Redirect user to homepage page after 5 seconds.
                          	header("refresh:2;url=home.php");
                          	exit; //
                          }
                          
                          
                          if ($_SERVER['REQUEST_METHOD'] == "POST")
                          { 
                          	if (isset($_POST["login_username_or_email"]) && isset($_POST["login_password"]))
                          	{
                          		$username_or_email = trim($_POST["login_username_or_email"]); //
                          		$password = $_POST["login_password"];
                          		
                                   
                          		//Select Username or Email to check against Mysql DB if they are already registered or not.
                          		$stmt = mysqli_stmt_init($conn);
                          		
                                  if(strpos("$username_or_email", "@") === true)
                          		{
                          			$email = $username_or_email;
                          			$username = "";
                          			
                          			$query = "SELECT ids, usernames, passwords, emails, accounts_activations_statuses FROM users WHERE emails = ?";
                          			// i = integer; s = string; d = double; b = blob.
                          			$stmt = mysqli_prepare($conn, $query);			
                          			mysqli_stmt_bind_param($stmt, 's', $email);
                          			mysqli_stmt_execute($stmt);
                          		    //$result = mysqli_stmt_get_result($stmt); //Use either this line (if you need to get all data of the array without associating them to variables like you do with mysqli_stmt_bind_result), or ...
                          			//Note from line below that the variables "$db_username", "$db_account_activation_status" are related to the tbl columns selected on $query ("SELECT ids, usernames, accounts_activations_statuses From users .. WHERE).
                          			$result = mysqli_stmt_bind_result($stmt, $db_id, $db_username, $db_password, $db_email, $db_account_activation_status); // ... this line. But not both.
                          		}
                          		else
                          		{
                          			$username = $username_or_email;
                          			$email = "";
                          			$query = "SELECT ids, usernames, passwords, emails, accounts_activations_statuses FROM users WHERE usernames = ?";
                          			// i = integer; s = string; d = double; b = blob.
                          			$stmt = mysqli_prepare($conn, $query);
                          			mysqli_stmt_bind_param($stmt, 's', $username);
                          			mysqli_stmt_execute($stmt);
                          			//$result = mysqli_stmt_get_result($stmt); //Use either this line (if you need to get all data of the array without associating them to variables like you do with mysqli_stmt_bind_result), or ...
                          			//Note from line below that the variables "$db_email", "$db_account_activation_status" are related to the tbl columns selected on $query ("SELECT ids, emails, accounts_activations_statuses From users .. WHERE).
                          			$result = mysqli_stmt_bind_result($stmt, $db_id, $db_username, $db_password, $db_email, $db_account_activation_status); // ... this line. But not both.#
                          		}       	
                          		
                          		//$rownums = mysqli_num_rows($result); // To get number of row matches
                          		//echo "$rownums";
                          		//Which of the following to do and why that one over others ?
                          		$row = mysqli_stmt_fetch($stmt);
                          		//$row = mysqli_fetch_array($query, MYSQLI_ASSOC);
                          		//$row = mysqli_fetch_array($result, MYSQLI_ASSOC);
                          		
                          		mysqli_stmt_close($stmt);
                          		
                          		printf("%s (%s)\n",$row["usernames"],$row["passwords"]);
                          		
                          		if ($result == false)
                          		{
                          			echo "'$result == false' on line 73! IF got triggered on line 73! !<br>";
                          			exit();
                          		}
                          		elseif ($row['accounts_activations_statuses'] == '0')
                          		{
                          			{
                          				echo "You have not activated your account yet! Check your email for instructions on how to activate it. 
                          				Check your spam folder if you don't find an email from us.";
                          				exit();
                          			}
                          		}
                          		else
                          		{
                          			echo "'$result == true' on line 73! Else got triggered on line 86! <br>";//This ELSE is getting triggered on the test. That means $result = TRUE;
                          		}
                          		
                          		if (password_verify($password, $db_password))		
                          		{
                          			echo "IF triggered for password_verify! password_verify ok";
                          			//If 'Remember Me' check box is checked then set the cookie. 
                          			//if(!empty($_POST["login_remember"])) // Either use this line ....
                          			if (isset($_POST['login_remember']) && $_post['login_remember'] == "on") // ...or this line. But not both!
                          			{
                          				setcookie("login_username", $username, time()+ (10*365*24*60*60));
                          			}
                          			else
                          			{
                          				//If Cookie is available then use it to auto log user into his/her account!
                          				if (isset($_COOKIE['login_username']))
                          				{
                          					setcookie("login_username","","");
                          				}
                          			}
                          			$_SESSION["user"] = $username;
                          			header("location:home.php?user=$username");				
                          		}
                          		else
                          		{
                          			echo "Else got triggered on line 111: Incorrect User Credentials ! 'password_verify = FALSE';<br>";
                          			exit();
                          		}
                          	}
                          }
                          	
                          ?>
                          
                          <!DOCTYPE html>
                          <html>
                          <head>
                          <title><?php $site_name?> Member Login Page</title>
                            <meta charset="utf-8">
                          </head>
                          <body>
                          <div class = "container">
                          <form method="post" action="">
                          <center><h3><?php $site_name ?> Member Login Form</h3></center>
                          <div class="text-danger">
                          <div class="form-group">
                          <center><label>Username/Email:</label>
                          <input type="text" placeholder="Enter Username" name="login_username_or_email" value="<?php if(isset($_COOKIE["login_username_or_email"])) echo $_COOKIE["login_username_or_email"]; ?>"</center>
                          </div>
                          <div class="form-group">
                          <center><label>Password:</label>
                          <input type="password" placeholder="Enter password" name="login_password" value="<?php if(isset($_COOKIE["login_password"])) echo $_COOKIE["login_password"]; ?>"></center>
                          </div>
                          <div class="form-group">
                          <center><label>Remember Login Details:</label>
                          <input type="checkbox" name="login_remember" /></center>
                          </div>
                          <div class="form-group">
                          <center><input type="submit" name="login_submit" value="Login" class="button button-success" /></center>
                          </div>
                          <div class="form-group">
                          <center><font color="red" size="3"><b>Forgot your password ?</b><br><a href="login_password_reset.php">Reset it here!</a></font></center>
                          <center><font color="red" size="3"><b>Not registered ?</b><br><a href="register.php">Register here!</a></font></center>
                          </form>
                          </div>
                          </body>
                          </html>
                          I am making a few changes on the above post's mentioned code because I was told in that forum (which I mentioned in my previous post):

                          1. Checking if $result is true/false is meaningless, as it will always be true if my code is bug-free, and likely always false if not.
                          2. Similarly, mysqli_stmt_fet ch() will return true if it found a result row, otherwise false.
                          I, instead need to check the value bound to $db_password to see if it's correct. So it might be something like:

                          Code:
                          if($row && password_verify($password, $db_password)) {
                          // good to go...
                          }
                          I have been advised 6 nights ago there on that forum to trim down my code to this:
                          Code:
                          if ($_SERVER['REQUEST_METHOD'] == "POST") // not really needed since you're checking $_POST
                          {
                              if (isset($_POST["login_username"]) && isset($_POST["login_password"])) {
                                  $username = trim($_POST["login_username"]); //
                                  $password = trim($_POST["login_password"]); //
                                  $hashed_password = password_hash($_POST["login_password"], PASSWORD_DEFAULT);
                                  $sql = "
                          SELECT
                            ids,
                            usernames, 
                            passwords, 
                            emails, 
                            accounts_activations_statuses 
                          FROM users 
                          WHERE usernames = ?
                            AND passwords = ?
                          ";
                                  $stmt = mysqli_prepare($conn, $sql);
                                  mysqli_stmt_bind_param($stmt, 'ss', $username, $hashed_password);
                                  mysqli_stmt_execute($stmt);
                                  if (mysqli_stmt_num_rows($stmt)) {
                                      // found a match, we're good to go...
                                  } else {
                                      // whatever you do when user/password not found...
                                  }
                              }
                          }
                          This forum Mod also managed to figure it that I got the column size wrong:
                          Php Programmers, It fails to log me in to my account with the correct Username/Email and Password. Do check the script on your end in Xampp/Wamp. Why is the password_verify failing on this script ? Did I get it wrong ? Thank You!

                          Comment

                          • bits2017
                            New Member
                            • Jun 2017
                            • 39

                            #14
                            Thanks Folks! Continuing this project on a new thread.
                            How do I mark this thread as resolved ?

                            Comment

                            Working...