Weird issue PASSWORD RESET!

Hi, i m trying to write a code for resetting password. I want this code to show in on the log in page (and the user should be able to open it without being logged in), however the problem i am facing is, whenever i open my recover form thus, localhost/pass.php , my recover form has a field for email and security question, ) it just shows the login page, which is localhost/login.php… i’m stuck on this now for days, and nothing seems to improve…

and just to make helping easier, i’m planning to implement a recover function thus:

  1. when the user clicks on forgot password on localhost/login.php without already being logged in, it should take them to a page,
    pass.php (displaying an email and security question)…

2.and when the users enter both( confirm if they exist in the sql table), then redirect to another form reset.php which shows two fields for “Enter new password” and “Confirm password”, and when user enters both, his password is updated in the database…

Pass.php has a template pass_form.php
and reset.php has a template reset_form.phpp

//code for pass.php:  
 
 
<?php
 
 
  // configuration
    require("../includes/config.php"); 
    
     if ($_SERVER["REQUEST_METHOD"] == "POST")
  {
     if (empty($_POST["forgotpassword"]))
     apologize("Please enter email address.");
     
     if (empty($_POST["security"]))
     apologize("Please enter your security key.");
     
    $email = $_POST["forgotpassword"]; 
    if(!(filter_var($email, FILTER_VALIDATE_EMAIL)))
    
     apologize("Please enter a valid email such as [email]example@domain.com[/email]");
     
     //check if email and securitykey exist in users table
     
    $check= query("SELECT id, security FROM users WHERE email = ?", $_POST["forgotpassword"]);
    if ($check === false)
    apologize("No such user in database");
  
   
    render("reset.php", ["title" => "Reset Password", "check" => $check]);
    
  }
  
  else  render("login_form.php", ["title" => "Login"]);
  
  
  
?>
  1. another problem is when i log in, and then i open localhost/pass.php, it always keeps on rendering the above template called login_form.php( which is linked to the controller login.php…) instead of displaying the pass_form.php
    template…
///  pass_form.php  is as follows:
 
<form action="pass.php" method="post">
    <fieldset>
        <div class="control-group">
            <input name="forgotpassword" placeholder="Email" type="text"/>
        </div>
        <div class="control-group">
            <input name="security" placeholder="Security Keyword" type="text"/>
        </div>
        <div class="control-group">
            <button type="submit" class="btn">Reset</button>
        </div>
    </fieldset>
</form>

RENDER() is a function as follows

function render($template, $values = [])
    {
        // if template exists, render it
        if (file_exists("../templates/$template"))
        {
            // extract variables into local scope
            extract($values);
 
            // render header
            require("../templates/header.php");
 
            // render template
            require("../templates/$template");
 
            // render footer
            require("../templates/footer.php");
        }
 
        // else err
        else
        {
            trigger_error("Invalid template: $template", E_USER_ERROR);
        }

Look at your else in pass.php you are telling it to load the login_form…

thanks for the reply…yeah, i tried removing that, but when i do that, i get a complete blank screen… i have no idea what causes that…(this happens when i’m logged in and i open pass.php, however, the other problem of redirecting to login.php too remains, when i’m logged out…

I think you need to tell it to render your forgot pass form template.

 else  render("pass_form.php", ["title" => "Forgot Password"]);

why didnt i think of that before.!!! i really appreciate your help…i’m sorry to be bothering you, another question, what do you think regarding the second issue,…not being able to access the pass.php from the login.php page?? it’s still happening, when ever i click on the hyperlink “forgot password” which links to pass.php, instead of that page opening, i get the login.php page???

found the solution to that problem, in my config.php file declared at the top, i was initializing SESSION…hence the problem…

however, the new issue now is my render function works for only templates, so it is rejecting render.php as an invalid template…

is there a way i can pass the values in the array $check to my reset.php (which is a controller , not template) , so i could access them in reset.php thus… (boldened)…
and is my logic right??

<?php
  
    
    // configuration
    require("../includes/config.php");

    // if form was submitted
   if(isset($_POST["submit"]))
    {
    
         if (empty($_POST["password"]))
        apologize("Please enter password.");
        
        
        if ($_POST["password"] != $_POST["confirmation"])
        apologize("Passwords do not match!");
        
        
         $result = query("UPDATE users SET hash = ? WHERE id = ?", crypt($_POST["password"], [B]$check[0]["id"]));[/B]
        
        if($result===false)
        apologize("Could not register. Please retry.");
        
        else
          {
          
          $rows = query("SELECT id FROM users WHERE hash = ?", crypt($_POST["password"]));
          $id = $rows[0]["id"];
          
          // remember that user's now logged in by storing user's ID in session
          $_SESSION["id"]= $rows[0]["id"];

         
        }
        
         // redirect to portfolio
          redirect("register.php");
       }
           
    
    else
    {
        // else render form
        render("register_form.php", ["title" => "Register"]);
    }
    
?>

I’m not sure I understand your question.

You have the following pages (that we know of) login.php, register.php, and reset.php. All of those pages should be built the same, meaning they should have a controller and template associated to them. Login template would have a link to reset.php and register.php, I would imagine you can setup reset.php exactly how you have register.php…

well,login.php, register.php, and reset.php are the controllers themselves … i’m planning to implement a recover function thus:

  1. when the user clicks on forgot password on localhost/login.php without already being logged in, it should take them to a page,
    pass.php ;inked to a template called pass_form.php displaying an email and security question)…

2.and when the users enter both( confirm if they exist in the sql table), then redirect to another form reset.php which shows two fields for “Enter new password” and “Confirm password”, and when user enters both, his password is updated in the database…

Pass.php has a template pass_form.php
and reset.php has a template reset_form.php

did i make myself clearer??
and it is this line in reset.php (code in my 3rd post)
$result = query(“UPDATE users SET hash = ? WHERE id = ?”, crypt($_POST[“password”], $check[0][“id”]));

which i want to get value for id in the array $check from the pass.php function (code in my first post) via this line in pass.php

render(“reset.php”, [“title” => “Reset Password”, “check” => $check]); … but this fails because reset.php is not a template, and the function works for only templates,…

what can i do??

So you are struggling with getting the data from pass.php to reset.php?

In other words, pass.php has its form submitted asking for e-mail and security question, the user submits that data and pass.php uses it to look up the user’s associated member ID. Then the user is redirected to reset.php where they are asked to enter their new password and confirm it. They submit the form and the reset.php should update the user’s password using member ID discovered on pass.php and the password they entered on reset.php.

Is that correct?

exactly!! that’s precisely what i’m trying to do… i’m new to php and this is kind of my first website, someone else suggested that i change everything, and make something new like a form that emails users a token, which is valid for sometime, which they ll use to reset their password…

i literally spent days on this one and don’t want to give up on this current one without knowing where i’m going wrong… thanks and looking forward to your reply…

Okay, my first suggestion is in the form processing of pass.php, store the member ID in session, something like

$_SESSION['ResetMemberId'] = $memberId;

Then in your reset.php form processing, read the value from session to use in your query, and then unset it.

$memberId = $_SESSION['ResetMemberId'];
unset($_SESSION['ResetMemberId']);

thanks for your help cpradio… :slight_smile: i understood that perfectly, but there are several issues now,

  1. if i enter an email, and a security question that does not correspond to the one i entered during registration, it still goes ahead and displays the reset.php file, instead
    of displaying “No such user in database”.

  2. $_SESSION[‘ResetMemberId’] … the ResetMemberId, can i use any other variable instead of ResetMemberId, or should it be the heading of id in my sql… for instance in my sql, the headings are id, email, security, hash (contains the hashed password").

  3. similar to 1, when i enter a new password in the “Enter new password” field on reset.php, and i try to enter another random password that doesnt match in the “Confirm Password” field, nothing happens, i mean no error is displayed, and instead of redirecting to my index.php file (the file that opens after users log in) , it keeps on displaying the same reset.php page…

this is what i’ve currently got for pass.php and reset.php …i ve cut the code down to the relevant parts…


//check if email and securitykey exist in users table
     
    $check= query("SELECT id FROM users WHERE email = ? AND security=?", $email, $_POST["security"]);
    if ($check === false)
    {
    apologize("No such user in database");
    }
    
     else
     {
    $_SESSION["id"] = $check[0]["id"];  
    redirect("reset.php");                      /////////////////////////////////////////////  SHOULD I REDIRECT TO RESET.PHP, OR SHOULD I RENDER the template, reset_form.php           
                                                                                                          instead??
    }
  }
  
  else  render("pass_form.php", ["title" => "Forgot Password"]);
  
  
?>


and my reset.php file is thus…


     
        $result = query("UPDATE users SET hash = ? WHERE id = ?", crypt($_POST["password"], $_SESSION["id"]));
        unset($_SESSION["id"]);  
        
        
        if($result===false)
        {
        apologize("Could not register. Please retry.");
        }
        else
          {
          
          $rows = query("SELECT id FROM users WHERE hash = ?", crypt($_POST["password"]));
          $id = $rows[0]["id"];
          
          // remember that user's now logged in by storing user's ID in session
          $_SESSION["id"]= $rows[0]["id"];
          // redirect to portfolio
          redirect("index.php");
         
        }
        
       }
              
    else
    {
        // else render form
        render("reset_form.php", ["title" => "Register"]);
    }
    
?>


thanks for your help cpradio… :slight_smile: i understood that perfectly, but there are several issues now,

  1. if i enter an email, and a security question that does not correspond to the one i entered during registration, it still goes ahead and displays the reset.php file, instead
    of displaying “No such user in database”.

  2. $_SESSION[‘ResetMemberId’] … the ResetMemberId, can i use any other variable instead of ResetMemberId, or should it be the heading of id in my sql… for instance in my sql, the headings are id, email, security, hash (contains the hashed password").

  3. similar to 1, when i enter a new password in the “Enter new password” field on reset.php, and i try to enter another random password that doesnt match in the “Confirm Password” field, nothing happens, i mean no error is displayed, and instead of redirecting to my index.php file (the file that opens after users log in) , it keeps on displaying the same reset.php page…

this is what i’ve currently got for pass.php and reset.php …i ve cut the code down to the relevant parts…


//check if email and securitykey exist in users table
     
    $check= query("SELECT id FROM users WHERE email = ? AND security=?", $email, $_POST["security"]);
    if ($check === false)
    {
    apologize("No such user in database");
    }
    
     else
     {
    $_SESSION["resetmemberid"] = $check[0]["id"];  
    redirect("reset.php");                      /////////////////////////////////////////////  SHOULD I REDIRECT TO RESET.PHP, OR SHOULD I RENDER the template, reset_form.php           
                                                                                                          instead??
    }
  }
  
  else  render("pass_form.php", ["title" => "Forgot Password"]);
  
  
?>


and my reset.php file is thus…


     
        $result = query("UPDATE users SET hash = ? WHERE id = ?", crypt($_POST["password"], $_SESSION["id"]));
        unset($_SESSION["id"]);  
        
        
        if($result===false)
        {
        apologize("Could not register. Please retry.");
        }
        else
          {
          
          $rows = query("SELECT id FROM users WHERE hash = ?", crypt($_POST["password"]));
          $id = $rows[0]["id"];
          
          // remember that user's now logged in by storing user's ID in session
          $_SESSION["id"]= $rows[0]["id"];
          // redirect to portfolio
          redirect("index.php");
         
        }
        
       }
              
    else
    {
        // else render form
        render("reset_form.php", ["title" => "Register"]);
    }
    
?>


Okay,

  1. put
    php var_dump($check);
    after your call to query() so you can see what value is returned when the email and security question do not match.
    Also, yes, I recommend using redirect to reset.php instead of just rendering the template. It is nice to have a physical page.
  2. I used ResetMemberId so it wouldn’t get confused with any SESSIONS you may be using for a Logged in user. I made it specific to Reset so there was little to no chance of it getting confused/conflicted with other pages. Think of it this way, if you use $_SESSION[‘id’] for a logged in user, and you just set it in pass.php to use $_SESSION[‘id’] as well, there is a good chance (depending on your validation) that I can go to a page that requires authentication without ever logging in.
  3. I don’t see where you are validating the password and confirm password match in your reset.php code. Can you provide more of the code for that page?

Hope this helps.

  1. i did that, and in fact this is what i did,
    $check= query(“SELECT id FROM users WHERE email = ? AND security=?”, $email, $_POST[“security”]);
    var_dump($check);
    if ($check === false),
    but it still goes ahead and displays the reset.php page…

this is my code for reset.php. sorry to bothering you… :frowning:


<?php
  
        // display errors, warnings, and notices
    ini_set("display_errors", true);
    error_reporting(E_ALL);
  // configuration
    require("../includes/constants.php"); 
    require("../includes/functions.php");

    // if form was submitted
   if(isset($_POST["submit"]))
    {
    
         if (empty($_POST["password"]))
        apologize("Please enter password.");
        
        
        if ($_POST["password"] != $_POST["confirmation"])
        apologize("Passwords do not match!");
        
        
        $result = query("UPDATE users SET hash = ? WHERE id = ?", crypt($_POST["password"], $_SESSION["resetmemberid"]));
        unset($_SESSION["resetmemberid"]);  
        
        
        if($result===false)
        {
        apologize("Could not register. Please retry.");
        }
        else
          {
          
          $rows = query("SELECT id FROM users WHERE hash = ?", crypt($_POST["password"]));
          $id = $rows[0]["id"];
          
          // remember that user's now logged in by storing user's ID in session
          $_SESSION["id"]= $rows[0]["id"];
          // redirect to portfolio
          redirect("index.php");
         
        }
        
       }
           
    
    else
    {
        // else render form
        render("reset_form.php", ["title" => "Register"]);
    }
    
?>


What did the var_dump produce? What was the output? Was $check actually set to false or something else?

As for the validation on reset.php, what does apologize do? Does it end execution? Otherwise, you need to make everything not apart of that if, in an else statement.

<?php
  
        // display errors, warnings, and notices
    ini_set("display_errors", true);
    error_reporting(E_ALL);
  // configuration
    require("../includes/constants.php"); 
    require("../includes/functions.php");

    // if form was submitted
   if(isset($_POST["submit"]))
    {
    
         if (empty($_POST["password"]))
           apologize("Please enter password.");
        else {
        
                if ($_POST["password"] != $_POST["confirmation"])
                        apologize("Passwords do not match!");
                else {
        
                        $result = query("UPDATE users SET hash = ? WHERE id = ?", crypt($_POST["password"], $_SESSION["resetmemberid"]));
                        unset($_SESSION["resetmemberid"]);  
        
        
                        if($result===false)
                        {
                                apologize("Could not register. Please retry.");
                        }
                        else
                        {
          
                                $rows = query("SELECT id FROM users WHERE hash = ?", crypt($_POST["password"]));
                                $id = $rows[0]["id"];
          
                                // remember that user's now logged in by storing user's ID in session
                                $_SESSION["id"]= $rows[0]["id"];
                                // redirect to portfolio
                                redirect("index.php");
         
                        }
                }
           }        
       }
           
    
    else
    {
        // else render form
        render("reset_form.php", ["title" => "Register"]);
    }
    
?>

var_dump produced nothing,when i went to localhost/pass.php and entered the email and security key, it just went ahead and displayed reset.php, and no output for
var_dump…

this is the function apolgize declaraed in functions.php

function apologize($message)
{
render(“apology.php”, [“message” => $message]);
exit;
}
and the apology .php file is as follows…



<p class="lead text-error">
    Sorry!
</p>
<p class="text-error">
    <?= htmlspecialchars($message) ?>
</p>

<a href="javascript:history.go(-1);">Back</a>


Try this:

//check if email and securitykey exist in users table
     
    $check= query("SELECT id FROM users WHERE email = ? AND security=?", $email, $_POST["security"]);
var_dump($check); die(); // comment this out afterwards, so you page processes
    if ($check === false)
    {
    apologize("No such user in database");
    }
    
     else
     {
    $_SESSION["resetmemberid"] = $check[0]["id"];  
    redirect("reset.php");                      /////////////////////////////////////////////  SHOULD I REDIRECT TO RESET.PHP, OR SHOULD I RENDER the template, reset_form.php           
                                                                                                          instead??
    }
  }
  
  else  render("pass_form.php", ["title" => "Forgot Password"]);
  
  
?>

I’m not sure why this isn’t working:

        if ($_POST["password"] != $_POST["confirmation"])
        apologize("Passwords do not match!");

That looks right to me, so long as the form names are correct, the apologize message should be invoked.