I began to learn code only three months ago, so it's possible for all the mystery to be just a beginner's mistake. Let's summarize the problem:
I made a CMS that still run well on localhost (wampserver with PHP 7.3) but suddenly stopped to run well on my domain (OVH hoster). What is mysterious is that the problem occurred when, after having relocated the CMS on a subdomain (it still worked then), I regenerated the LetsEncrypt SSL certificates (at this point it stopped working).
I contacted the hoster: apparently the SSL certificates are fine. The pages that stopped working all use session variables : captcha, forgot, login, logout, registration.
So I checked many session variables problems threads here, but it still didn't help for my situation.
For example: I tried to var_dump some session variables on the subdomain: nothing strange, it shows exactly what is expected. I then wondered if it was a CHMOD problem so I checked if all the files were actually CHMOD 644 : they are. I tried to revert back to PHP 7.2 : changed nothing. I even removed some .htaccess files to check if they were so poorly setted it caused the problem: changed nothing (I put them back since).
My hosting plan won't allow me to access php.ini to compare the server version with my local version. So I'm kind of stuck.
Update
I have a new hypothesis: the server doesn't handle my POST methods as it handled them before. In the developer tools, the echoed POST method file was just "/".
I added the following condition to my ifItIsMethod function (the function is described at the end of this post):
if(empty($_SERVER['CONTENT_TYPE'])) {
$_SERVER['CONTENT_TYPE'] = "application/x-www-form-urlencoded";
}
and now the POST method file returns "index", which sounds like a progress. I'll edit tomorrow my .htaccess files to set the post_max_size, but the new hypothesis is HTTP (or IIS) messing up with POST.
Day 7:
setting the attribute "name" to "submit" in the input field doesn't change the result
editing the post_max_size in .htaccess is forbidden by the hoster (it returns a 500 Internal Server Error)
var_dump($_POST) echoes what is normally expected (nothing from the form is missing)
So I var_dumped each variable of my (very basic) login_user function:
function login_user($username, $password)
{
global $connection;
$username = escape($username);
$password = escape($password);
$query = "SELECT * FROM users WHERE user_name = '{$username}' ";
$select_user_query = mysqli_query($connection, $query);
if (!$select_user_query) {
die("QUERY FAILED");
}
while($row = mysqli_fetch_assoc($select_user_query)) {
$db_id = $row['user_id'];
$db_name = $row['user_name'];
$db_password = $row['user_password'];
$db_firstname = $row['user_firstname'];
$db_lastname = $row['user_lastname'];
$db_email = $row['user_email'];
$db_role = $row['user_role'];
}
$password_verify = password_verify($password, $db_password);
if($username === $db_name && $password_verify === true) {
$_SESSION['user_id'] = $db_id;
$_SESSION['user_name'] = $db_name;
$_SESSION['user_firstname'] = $db_firstname;
$_SESSION['user_lastname'] = $db_lastname;
$_SESSION['user_email'] = $db_email;
$_SESSION['user_role'] = $db_role;
redirect("admin");
} else {
redirect("index");
}
}
$row has all the expected informations
$_SESSION has nothing...
... but it's because password_verify() returns "false"
The new hypothesis was then: maybe a change in the server messed up with the password decryption, let's just try to change it.
But the forgot page is also broken! And this functionnality doesn't use password_verify.
Its PHP part is as follows:
if(ifItIsMethod("post")) {
if(isset($_POST['email'])) {
$email = escape($_POST['email']);
$length = 50;
$token = bin2hex(openssl_random_pseudo_bytes($length));
if(email_exists($email)) {
$query = "UPDATE users SET token = ? WHERE user_email = ?";
$stmt = mysqli_prepare($connection, $query);
mysqli_stmt_bind_param($stmt, "ss", $token, $email);
mysqli_stmt_execute($stmt);
mysqli_stmt_close($stmt);
$mail = new PHPMailer(true);
$mail->isSMTP(true);
$mail->Host = SMTP_HOST;
$mail->Username = SMTP_USER;
$mail->Password = SMTP_PASSWORD;
$mail->Port = SMTP_PORT;
$mail->SMTPAuth = true;
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->isHTML(true);
$mail->CharSet = "UTF-8";
$mail->setFrom('postmaster@raphaelbadawi.fr', 'RB Blog Postmaster');
$mail->addAddress($email);
$mail->Subject = "RB Blog - Réinitialisation de votre mot de passe utilisateur";
$mail->Body = "<h4>Bonjour,</h4><p>Cliquez sur le lien suivant pour réinitialiser votre mot de passe : <a href='https://blog.raphaelbadawi.fr/reset.php?email=" . $email . "&token=". $token ."'>lien</a>.</p><small>L'équipe RB Blog</small>";
if($mail->send(true)) {
$emailSent = true;
}
} else {
$msg = "Cette adresse ne correspond à aucun utilisateur connu";
}
}
}
And here is the ifItisMethod function:
function ifItIsMethod($method = null) {
if(empty($_SERVER['CONTENT_TYPE'])) {
$_SERVER['CONTENT_TYPE'] = "application/x-www-form-urlencoded";
}
if($_SERVER['REQUEST_METHOD'] == strtoupper($method)) {
return true;
} else {
return false;
}
}
I don't know what to do next.
Day 8 :
Checked the SQL tables just in case: token is text, password is varchar 255, seems fine.
Day 8.5 :
PROBLEM SOLVED! The database contained passwords that were hashed locally. Rehashing them using the remote server basically solved the login. The forgot function was buggy because of an obsolete $_GET check I forgot to mute at the top of the page (in the first version of this function, the token was passed through the URL).
I wanted to thank you all for all the time and mind you put into this issue. It did help eliminate some hypothesis. Without you I would surely still be at it. Thanks!