php - Why do attempts to update a user's password in this Codeigniter 3 application fail?
Get the solution ↓↓↓I am working on a basic blog application in Codeigniter 3.1.8 and Bootstrap 4.
I have added a registration and login system to this application. I am current working on a password reset system.
I can't figure out why updating a user's password fails as below:
In the Newpassword controller I have:
class Newpassword extends CI_Controller {
private $token = NULL;
public function index($token = NULL) {
//echo $token; die();
$data = $this->Static_model->get_static_data();
$data['pages'] = $this->Pages_model->get_pages();
$data['tagline'] = 'New password';
$data['categories'] = $this->Categories_model->get_categories();
$this->token = $token;
// Form validation rules
$this->form_validation->set_rules('password', 'Password', 'required|min_length[6]');
$this->form_validation->set_rules('cpassword', 'Confirm password', 'required|matches[password]');
$this->form_validation->set_error_delimiters('<p class="error-message">', '</p>');
if(!$this->form_validation->run()) {
$this->load->view('partials/header', $data);
$this->load->view('auth/newpassword');
$this->load->view('partials/footer');
} else {
$this->add();
}
}
public function add() {
$data = $this->Static_model->get_static_data();
$data['pages'] = $this->Pages_model->get_pages();
$data['tagline'] = 'New password';
$data['categories'] = $this->Categories_model->get_categories();
// Encrypt new password
$enc_password = password_hash($this->input->post('password'), PASSWORD_DEFAULT);
// Update password column
$token = $this->token;
if ($this->Usermodel->set_new_password($token, $enc_password)) {
redirect('login');
$this->session->set_flashdata("new_password_success", "Your new password was set. You can login");
} else {
$this->session->set_flashdata("new_password_fail", "We have failed updating your password");
redirect('/newpassword');
}
}
}
In the Usermodel model I have:
public function set_new_password($token, $enc_password) {
$this->db
->where(['token' => $token])
// set new password and reset token to NULL
->update('authors', array('password' => $enc_password, 'token' => NULL));
}
The form:
<?php echo form_open(base_url('newpassword/add')); ?>
<div class="form-group <?php if(form_error('password')) echo 'has-error';?>">
<input type="password" name="password" id="password" class="form-control" placeholder="Password">
<?php if(form_error('password')) echo form_error('password'); ?>
</div>
<div class="form-group <?php if(form_error('cpassword')) echo 'has-error';?>">
<input type="password" name="cpassword" id="cpassword" class="form-control" placeholder="Confirm password">
<?php if(form_error('cpassword')) echo form_error('cpassword'); ?>
</div>
<div class="form-group mb-2">
<input type="submit" value="Set password" class="btn btn-block btn-md btn-success">
</div>
<?php echo form_close(); ?>
If I uncomment//echo $token; die();
from the controller, the token is printed with the expected value. Yet, the password does not update (and the failure to update it is correctly displayed).
What am I doing wrong?
Answer
Solution:
When you click Set password button redirected tonewpassword/add
but the token not exists here, because used it only a previous step:
- Password reset request
- Click link in email (token exist)
- Fill the form and click "Set password" (send form data to newpassword/add) - the token is not exist here but you want to use it:
$token = $this->token;
but now the "token" is: add
Sorry, you must be refactoring your password reset code logic. I think this is harder to fix than rewriting the whole process
UPDATE:
Add$data['token'] = $token;
into index method in Newpassword controller
AND
modify form action url inviews/auth/newpassword.php
to this:<?php echo form_open(base_url('newpassword/add/'.$token)); ?>
IMPORTANT!!!
Add return to ell functions in model:return $this->db-> ....
And putredirect('<url>')
after set session flashdata!
I tested it and I think fixed the problem.
Answer
Solution:
This is the final, working code for the password update (in case anybody else needs it):
In the Newpassword controller:
class Newpassword extends CI_Controller
{
public function index($token = NULL)
{
$data = $this->Static_model->get_static_data();
$data['pages'] = $this->Pages_model->get_pages();
$data['tagline'] = 'New password';
$data['categories'] = $this->Categories_model->get_categories();
$data['token'] = $token;
// Form validation rules
$this->form_validation->set_rules('password', 'Password', 'required|min_length[6]');
$this->form_validation->set_rules('cpassword', 'Confirm password', 'required|matches[password]');
$this->form_validation->set_error_delimiters('<p class="error-message">', '</p>');
if (!$this->form_validation->run()) {
$this->load->view('partials/header', $data);
$this->load->view('auth/newpassword');
$this->load->view('partials/footer');
} else {
// Encrypt new password
$enc_password = password_hash($this->input->post('password'), PASSWORD_DEFAULT);
if ($this->Usermodel->set_new_password($token, $enc_password)) {
$this->session->set_flashdata("new_password_success", "Your new password was set. You can login");
redirect('login');
} else {
$this->session->set_flashdata("new_password_fail", "We have failed updating your password");
redirect('/newpassword/' . $token);
}
}
}
}
In the model:
public function set_new_password($token, $enc_password) {
return $this->db
->where('token', $token)
// set new password and reset token to NULL
->update('authors', array('password' => $enc_password, 'token' => NULL));
}
The form (view):
<?php echo form_open(base_url('newpassword/'. $token)); ?>
<div class="form-group <?php if(form_error('password')) echo 'has-error';?>">
<input type="password" name="password" id="password" class="form-control" placeholder="Password">
<?php if(form_error('password')) echo form_error('password'); ?>
</div>
<div class="form-group <?php if(form_error('cpassword')) echo 'has-error';?>">
<input type="password" name="cpassword" id="cpassword" class="form-control" placeholder="Confirm password">
<?php if(form_error('cpassword')) echo form_error('cpassword'); ?>
</div>
<div class="form-group mb-2">
<input type="submit" value="Set password" class="btn btn-block btn-md btn-success">
</div>
<?php echo form_close(); ?>
Share solution ↓
Additional Information:
Link To Answer People are also looking for solutions of the problem: the metadata storage is not up to date, please run the sync-metadata-storage command to fix this issue.
Didn't find the answer?
Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.
Similar questions
Find the answer in similar questions on our website.
Write quick answer
Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.