My login authentication is stuck on a line

My login script should take an email and password then check if they exist in the database. If they do and no errors are returned, set session and redirect. The email check validates successfully but the password doesn’t so that part in my code is commented out.
The primary issue however is when I intend testing if any errors were returned, the script just gets stuck at that point. My code below

$user_email = $_POST['email'];
$user_password = $_POST['password'];
$my_array = unserialize(file_get_contents('all_users.php'));

if (isset($user_email, $user_password)) {
	if (isset($_SESSION['username'])) {
		header('Location:my site.com/');
	}
	else {
	$approved = auth_user($user_email, $user_password);
	if ((!isset($_SESSION['error'])) || is_null($_SESSION['error'])) {
	echo $approved; /* this line echoes the username just before this "if" condition but fails to echo as it is now despite no errors being set */
		$_SESSION['username'] = $approved;
		foreach($my_array as $user) {
			if ($user['username'] == $approved) {
			$user->set_last_login();
			}
		}
		header('Location: mysite.com/');
	}
	}
}

function auth_user($email, $password){
	$mysqli = mysqli_connect("localhost", "xxxx",  "xxx", "xxxx");
	$query = "SELECT * FROM user WHERE email='" . $email . "'";
	
	if ($registered = mysqli_query($mysqli, $query)) {
	if (mysqli_num_rows($registered) == 0) {
		$_SESSION['error'] = 'incorrect email';
		return;
	}
	/*else if (!password_verify($password, mysqli_fetch_assoc($registered)['password'])) {
		$_SESSION['error'] = 'incorrect password';
		return;
	}*/
	else {
		while ($row = mysqli_fetch_assoc($registered)){
		return $row['username'];
		};
	}
	mysqli_close($registered);
	}

}

Can anyone figure out what could be wrong since I cannot log in into my own app?

Precisely which line does it hang on? Is it the $user->set_last_login() line? What does that code do? Can you show (sanitised, of course) what’s in “all_users.php”?

This line

I commented that–if I echo the result of that authentication outside that line, it outputs correctly but not if I echo it inside. That probably means the $_SESSION['error'] was set but the session shouldn’t be set if the records match(and they do match because what is echoed is what I stored at the database).

Besides, there is an event in the page that should occur in the page if that $_SESSION['error'] is set and that event is not triggered meaning it was not set.
All_users file is a data file containing a bunch of user preferences.

Could there be anything left in $_SESSION[‘error’] from earlier in the code? You don’t clear it inside the function when you find a valid username, so if it already had something in it, it would still be there.

Also, is it possible in PHP to cause stack trouble that might affect anything? I notice in your function that you use a while() loop to get the results from your query once you’ve established that there is at least one result, and you return the username from within that while() loop, rather than exiting it first. Indeed if the username database requires the email to be unique, there is surely no need for the while loop, and you could instead do something like:

function auth_user($email, $password){
  $mysqli = mysqli_connect("localhost", "xxxx",  "xxx", "xxxx");
  $query = "SELECT * FROM user WHERE email='" . $email . "'";
	
  if ($registered = mysqli_query($mysqli, $query)) {
    if (mysqli_num_rows($registered) == 0) {
      $_SESSION['error'] = 'incorrect email';
      mysqli_close($mysqli);  // not $registered
      return;
      }

    $row = mysqli_fetch_assoc($registered);
    mysqli_close($mysqli);
    if (!(password_verify($password, $row['password']))) { 
      $_SESSION['error'] = 'incorrect password';
      return;
      }
    // must be OK
    unset($_SESSION['error']); // or however you clear the error variable
    return $row['username'];
    }
  }

There’s an argument that it’s better to return non-specific error messages for bad logins rather than helpfully telling someone whether it’s the password or email address that they got wrong.

1 Like

That logged me in. You were right about some evil force setting the error variable in the sessions array. The password check however does not occur and even when I input wrong password, it still validates and redirects me to the homepage.
I have this in the body of the sign up page to indicate when wrong password or email is input but it does not show when either happens. Just redirects anyways
<?php if (isset($_SESSION['error'])) { echo '<p style="color:#eee;">*incorrect email or password</p>'; } ?>

And there is a clause in the first code block that should check if the session username has been set, then if yes, redirect to landing page but it doesn’t. The sign in script just loads anyways.

Is the location correct in the first relocate (the one where it checks for $_SESSION[‘username’]), in that it has a space in it? Don’t you need to exit after you’ve done a redirect, otherwise the code continues operation after the header is output?

As for why it signs you in even on an incorrect password, you’d have to look in the password_verify() function for that I suspect. It needs to return true or false by the look of it.

Yes. The location is the same as the one after the normal authentication. I posted this as a dummy. Are you suggesting I do
header('location:new.location'); exit(); ?
The password_verify function returns a boolean that’s why I’m testing correct/wrong values with this line
if (!password_verify($password, $row['password'])) {
Is there a better way to do the verification?

Yes, it does seem that you need an exit(); after you output the header. Remember that header() only sends a header to the browser, without examining what’s in it. So if you then go on to execute more code, it will still run even though you’ve already sent that header.

Yes, I saw that you’re testing for a false return from password_verify. My point was that if it’s falsely allowing you in even though the passwords don’t match, then the issue must be in password_verify().

I put the following in the beginning of the script since I figured the sign up page pops up whether the user is already logged in because the session array is in fact, not set.
session_name($approved); $time = 60 * 60 * 24 * 3; session_set_cookie_params($time, '/', '.agwconitsha.org'); setcookie(session_name(), $approved, $time);

And this at the end of the script
session_write_close(); exit();

It still did me no good! :confounded: print_r($_SESSION['username'] does nothing while echo session_name (on the redirected page) outputs PHPSESSID even though that should have changed based on the code snippet in this comment.

It’s also curios that the browser does not ask me if it should save the password for this page after the supposed login. Session error variable refuses to be set when wrong values are input. Does it mean the session array variable cannot persist within pages? Why does the redirected page totally ignore the session variables from the previous page?

Lastly, how do I fix the password_verify function? It’s a built-in function and my parameters are based on what they have in the manual

Do you have session_start() at the very beginning of your PHP code, in each and every page that will require access to the session variables? I don’t think they’ll persist without that, I just assumed it was before the code you posted. How do you submit the login form to your PHP code, using a standard submit or with some JavaScript? I’ve read that the latter can cause some issues in some browsers with making it prompt to store the details.

As for password_verify(), it tells you what I know by the fact I hadn’t realised this was a standard PHP function - it’s not something I’ve used, so I can’t guess why it would return a false positive. If you echo the $password and $row[‘password’] variables immediately before the check, and write a three-line bit of code to verify those details without anything else, does it work or not work?

<?php
$pw = 'mypassword';
$pwfromdb = '$dsgsbnsrtwo20rh20rh202'; // get these values from the echo output
echo password_verify($pw, $pwfromdb);
?>

Yipee!! :smiley: :smile: everything now works seamlessly. The password verify verifies accordingly and indicates when wrong password is entered. When the password is correctly input, it redirects to the landing page. The homepage also recognizes the login session from the previous session and outputs sign in/sign out depending on user status. Here’s what I changed
if (isset($_SESSION['error'])) { unset($_SESSION['error']); } //first code block prefix
else { $row = mysqli_fetch_assoc($registered); mysqli_close($registered); if (!password_verify($password, $row['password'])) { return $_SESSION['error'] = 'incorrect password'; } unset($_SESSION['error']); return $row['username']; }
Thanks for your time @droopsnoot

@droopsnoot one last thing: The favicon keeps showing the web hosting provider’s icon despite me linking to the main domain(as I’m building something on a subdomain) should I contact them about this or is there something I’m doing wrong?

Sorry, no idea on that I’m afraid. Probably worth asking them whether there are specific location(s) for it.

Hi , I Have made some changes in your function Could you please try this

<?php function auth_user($email, $password) {
    mysql_connect("localhost", "xxxx", "xxx");
    mysql_select_db("database-name");
    $registered = mysql_query("SELECT username FROM user WHERE email='" . $email . "' AND password='$password'");
    if (mysql_num_rows($registered) == 0) {
        $_SESSION['error'] = 'incorrect email';
        return;
    }
    /* else if (!password_verify($password, mysqli_fetch_assoc($registered)['password'])) {
      $_SESSION['error'] = 'incorrect password';
      return;
      } */
    while ($row = mysql_fetch_row($registered)) {
        return $row[0];
    }
    mysql_close($registered);
}
?>

Veggiebuzz

Can I ask what you’ve added to the function? It seems that you’ve taken the original code, and changed the more modern mysqli() calls to use the old, no-longer-supported mysql_query() and related functions. It also doesn’t reset the session error variable which was causing a problem for the OP.

I suspect adding the password into the query won’t work either, because the password stored in the database in the encrypted version, so it will never match the $password variable as that’s the plain-text version the user typed in.

That would be the last place I’d consider to have a problem - that function would have been thoroughly tested before it was added to PHP 5.5. Plus unless you go back to the PHP source code you wouldn’t have access to the code within that built in function anyway.

Yes, I mentioned in #10 that I hadn’t realised it was a standard PHP function, thinking it was something the OP had written to verify their passwords.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.