Problem with POST[]

I have a login form


if I enter the wrong credentiallls, I get an error message (which closes after 3.5 seconds) using

<div id="login" class="overlay">
	<div class="popup">
		<div class="content">
		  <a class="close" id="close_login" href="#">&times;</a>
			<div class="card m-0">
		      <h3 class="card-header">
			  <span class="icon-signin"></span>&nbsp;&nbsp;Login		
			  </h3>
				<div class="card-body">
					<div class="alert alert-light border border-light shadow-sm" role="alert">
					  <form action="" method="POST">
						<div class="form-group">
						  <label for="Email">Email</label>
							<div class="input-group">
								<div class="input-group-prepend">
								  <span class="input-group-text text-secondary">@</span>
								</div> 
							  <input type="email" class="form-control" id="Email" name="Email" required>
							</div>
						</div>
						<div class="form-group">
						  <label for="Password">Password</label>
							<div class="input-group">
								<div class="input-group-prepend">
								  <span class="input-group-text text-secondary"><i class="icon-lock"></i></span>
								</div> 
							  <input type="password" class="form-control" id="Password" name="Password" required>					
							</div>
						</div>
						<div class="form-row">
							<div class="col">
							 <button class="btn btn-dark btn-block" name='loginSubmit' type="submit"><span class="icon-ok"></span>&nbsp;&nbsp;Submit</button>
							</div>
						</div>
					  </form>
					</div>
					  <!--<h6 class="text-right text-secondary"><a href="#forgot_password">Forgot Password</a></h6>-->
				</div>
			</div>
		</div>
	</div>
</div>
<?php if(isset($_POST['loginSubmit'])){ ?>
<div id="login_result" class="overlay" style="visibility:visible; opacity:1">
	<div class="popup">
		<div class="content">
		  <a class="close" id="close_login" href="#">&times;</a>
			<div class="card m-0">
		      <h3 class="card-header" style="color:<?=$popup_card_text_color?>; background-color:<?=$popup_card_header_background?>">
			  <?=$popup_card_header?>
			  </h3>
				<div class="card-body" style="color:<?=$popup_card_text_color?>; background-color:<?=$popup_card_body_background?>">
				<?=$popup_card_body?>
				</div>
			</div>
		</div>
	</div>
</div>
<script>
 document.getElementById("login").style.display = "none"; 
 setTimeout(function(){
  document.getElementById("login_result").style.display = "none"; 
 }, 3500);
</script>
<?php } ?>

the login form in at the login id so the URL becomes index.php#login
How can I (after submitting the login form, change the URL to only the page (index.php) and not the #login target?

so… where is your logic to handle the login?

this

<?php
if(isset($_POST['loginSubmit'])) {
	
	if(empty($_POST['Password']) || empty($_POST['Email']) || !filter_var($_POST['Email'],FILTER_VALIDATE_EMAIL)) {
		$popup_card_body_background = '#f8d7da';
		$popup_card_text_color = '#721c24';
		$popup_card_header_background = '#f5c6cb';
		$popup_card_header = '<span class="icon-error"></span>&nbsp;&nbsp;Login Fail!';
		$popup_card_body = '<p class="card-text">You are NOT logged in.</p>';
	} else {
		$popup_card_body_background = '#d4edda';
		$popup_card_text_color = '#155724';
		$popup_card_header_background = '#c3e6cb';
		$popup_card_header = '<span class="icon-ok"></span>&nbsp;&nbsp;Success!';
		$popup_card_body = '<p class="card-text">You are logged in.</p>';
		
		$sql = "SELECT user_id, role FROM users WHERE email = ? AND pass = ? AND operational_status = 1";
		//echo $sql;
		$user = $_POST['Email'];
		$pass = $_POST['Password'];

		$result = $pdo->prepare($sql);
		//add the parameters
		$result->execute([$user, $pass]); 
				
		if($row = $result->fetch()){    
		   $_SESSION['email']  = $user;
		   $_SESSION['user_id'] = $row['user_id'];
		   $_SESSION['user_role'] = $row['role'];
		   $_SESSION['id'] = session_id();
					 
		   $update = $pdo->prepare( "UPDATE users SET session_id = ? WHERE email = ?");
		   $update->execute([$_SESSION['id'], $_SESSION['email']]);
		} else {
		$popup_card_body_background = '#f8d7da';
		$popup_card_text_color = '#721c24';
		$popup_card_header_background = '#f5c6cb';
		$popup_card_header = '<span class="icon-error"></span>&nbsp;&nbsp;Login Fail!';
		$popup_card_body = '<p class="card-text">You are NOT logged in.</p>';
   		}	
	}
}
?>

I shall leave it to others to come along and scream at you for using a plaintext password…

The Javascript line to do what you want is history.replaceState(null, "", "index.php");

2 Likes

I’m going to encrypt the password next.

I thought window.locatilon.pathname would do it, no?

image

<script>
 document.getElementById("login").style.display = "none"; 
 setTimeout(function(){
  document.getElementById("login_result").style.display = "none"; 
  location.replace = window.location.pathname;
 }, 3500);
</script>

What’s the error message? It would be helpful for anyone else trying to help you debug your code. Is it also custom error message or default PHP error message?

ok, this seems to wor k

<script>
 document.getElementById("login").style.display = "none"; 
 setTimeout(function(){
  document.getElementById("login_result").style.display = "none"; 
  window.location.href = "<?=$_SERVER['PHP_SELF']?>";
 }, 3500);
</script>

changing window.location will reload the page, is the only difference.

I’m sure you’ve been told before that this is not the way to check for submission of a form.

o. o That wasn’t what I was asking though. I was asking what error message are you seeing on the screen. You can’t just say “I see an error message” and not elaborate on it. That doesn’t give anyone any information so they can help you. You can reduce the amount of time spent trying to debug what you’re having an issue with if you just tell everyone the error messages you’re seeing and what you’re expecting the screen’s behavior to be like when you aren’t seeing the error messages. That’s equivalent to the infamous “It doesn’t work” response. Like “Ok, what doesn’t work? The screen? The mouse? The computer? The website? The internet? The world? What exactly isn’t working?”

2 Likes

OK, I’ll be the one. :grin:
But only because I hear this kind of thing a lot around here:-

I’m sorry but I’m always a bit skeptical about when I (often) hear people say that they will fix all the security holes that were pointed out after they get their script/application working.
Only becuase to me it makes little sense to spend time working on a script to make it work, when it is known to work the wrong way, so you subsequently have then go back and re-write it again to make it work the right way.
So I tend to interpret it as: I’m going to get it working as is, then not touch anything for fear of breaking what appears to be working. This isn’t necessarily you, but I see it enough with many others that it has to be said.

How to fix.
It will take a little more than just hashing what is already stored, as proper password verification will alter the login logic that you already have there. Though it is nothing too daunting.

First thing is to hash the existing words.
This should be run only once. Also it’s not tested in the wild, I I suggest backing up the table before you run in case I mande a mistake. Make sure the password field is long enough to hold a hash.

// Where $pdo is assumed to be your DB connection
$sql = $pdo->query("SELECT user_id, pass FROM users"); 	// Get all user accounts, ID & password
if($users = $sql->fetchAll(PDO::FETCH_KEY_PAIR)){			// Key Pair will be easy to work with
	$sql = $pdo->prepare("UPDATE users SET pass = ? WHERE user_id = ?");	// Prepare to update
	foreach($users as $id => $pass){
		$hash = PASSWORD_HASH($pass, PASSWORD_DEFAULT);	// Hash each word
		$sql->execute([$hash, $id]);					// Execute the updates
	}
}

Needless to say, this is not part of the login, but a separate standalone run once script.

To alter the login logic, you will fetch the (hashed) password, you can’t search by it because nothing outside of the table should know what the hash is.

$sql = "SELECT user_id, role, pass FROM users WHERE email = ? AND operational_status = 1";

You can then verify the posted password against the fetched hash:-

if(password_verify($_POST['Password'], $row['pass'])) {
      // Good
}
else{
     // Not good
}

And that should do it.

2 Likes

I was going to say something, but glad you did it instead. :wink:

I was going to say hashing passwords in PHP isn’t as complicated as other languages. A mouse with no hands could have hashed the passwords. It’s literally trivial at this point. All you just need is wrap your “raw” string or variable holding the “raw” string inside the password_hash() function and that’s it. You have just hashed your very first and very powerful hashed password. It’s that simple.

Other languages force you to do like byte conversions and what not to then use as the salt and then you then do this hoopty-loop (doing hand gestures) to then do this… you know type of thing. Where as with PHP, it’s so simple and straightforward a dummy could easily hash the passwords in the powerful built-in PHP hash. It’s literally 1 line of code, more specifically 34 characters long excluding whatever you want to hash in the user specified section of the function.

There will also need to be hashing in the sign up form processing too, but that is very simple to do.

2 Likes

Exactly, which is why it makes no sense to say I’ll come back and fix it later. Do it right to start with makes much more sense.

1 Like

It also becomes more of a hassle later on, as you then have to code something to pull all the passwords out of the current database, hash them, and reinsert them, when you could… just do it from the start.

2 Likes

its that easy? I alway thought it would be a lot more involved…Thanks…

There is an exapmle in post #11.
The first block of code will select all user passwords, hash them, then update the database to the hashed values.
But as said, be sure to back up the table first, in case there is a problem. And be sure to check the string length of the password column is long enough, the hash can be quite long, future ones may be longer.

The next part shows how to alter the login to verify the hash.
The only part you are missing is the sign up part which will need the hash function adding.

1 Like

Yup. It’s that easy. @SamA74 gave you a good example, but it’s all about muscle memory tbh.

password_hash('raw_data_here', PASSWORD_DEFAULT);

First argument is always your raw data or your variable. Second argument is always the constant for what you want to use. Typically PASSWORD_DEFAULT is used.

And that’s it. You have just hashed your very first password. Like I said in my post #12. It’s literally 34 characters long excluding what you put in the first argument. Everything is done behind the scenes and uses bcrypt. The hashed password, cost, salt, and hashing algorithm is all done by PHP and this is much much much much safer than using any homegrown or botched password hashing function using things like MD5 and SHA.

just make sure you only ever run that script once… :wink:

(have had people leave something like that laying around on a server, and then wonder why suddenly none of their logins work…)