I have a dashboard with users details which they can edit. I would like to add a password change but before they can change their password how would I validate their current password before letting them change to a new password?
So the form would have 3 fields. First field will have their current_password, follow by new_password and confirm_password.
codeigniter comes with a Form Validation Class you can find the documentation here.
Its purpose is exactly what its name suggest - It will help you validating your form input. Once you get used to it it comes in really handy.
This is how your controller could look:
public function change_password() {
if ($this->input->post()) {
// user submitted the form
if (some_encryption_function($this->input->post('current_password'))==password_from_db) { // pseudo code
$this->load->library('form_validation'); // this should probably belong somewhere else like in the constructor of the controller
$this->form_validation->set_rules('new_password', 'New Password', 'trim|required|min_length[4]|max_length[12]|matches[confirm_password]');
$this->form_validation->set_rules('confirm_password', 'Confirm Password', 'trim|required|min_length[4]|max_length[12]');
if ($this->form_validation->run() == false) {
data['message'] = validation_errors();
} else {
store_new_password_to_db($this->input->post('new_password');
data['message'] = "Some success message";
}
$this->load->view('your_change_password_view',$data);
}
}
}
This is not a perfect example for the form validation class. Just because you could easily validate those 3 fields without its help. But as its already built in with codeigniter why not use it?
Have them enter their old pass, new password and confirm the new password. Then,
if (old pass == password stored in database)
{
if (new password == confirm password)
{
//update password in database
}
}
$oldPass = get_password_from_db();
$currentPass = $this->input->post("old_pass");
$newPass = $this->input->post("new_pass");
$confPass = $this->input->post("conf_pass");
//check if new and confirm pass are same
if(md5($currentPass) == $oldPass) {
//update query to change to new pass
}
Hope it helps
Related
I have created a registration system where password are storing in bycript form. But While I am trying to validate for login purpose, it's saying wrong password . My code for authentication is given bellow :
public function authenticate(Request $request){
$email=$request->post('email');
$password=$request->post('password');
$result=Admin::where(['email'=>$email,'password'=>$password])->get();
if(isset($result['0']->id)){
$request->session()->put('ADMIN_LOGIN',true);
$request->session()->put('ADMIN_ID',$result['0']->id);
return redirect('admin');
}else{
$request->session()->flash('error','Please enter valid login details');
return redirect('admin-login');
}
}
You don't need to be building your own authentication system, but this would be the flow:
use App\Models\Admin;
use Hash;
...
public function authenticate(Request $request)
{
...
if ($user = Admin::where($request->only('email'))->first()) {
if (Hash::check($request->input('password'), $user->password)) {
// login
}
}
// not authenticated
}
You have to find the user by an identifier, so 'email' is used here. You can't query against the password because it is a hash. If you get a user from the query you can then do a hash check on the submitted password and the user's password from the record.
This is a simplified version of what SessionGuard::attempt/Auth::attempt([...]) is doing.
You have to find the admin by email like this:
$admin = Admin::where(['email'=>$email])->first();
and than compare the hashes
if ($admin && Hash::check($admin->password, $password)) {
// ... logged in
} else {
// ... not legged in
}
When your request is processed password comes as plain text while password in your database is hashed.
So you have to bcrypt or hash your password first to properly make your query.
You can:
$password = Hash::make($request->post('password'));
Or:
$password = bcrypt($request->post('password'));
Both Hash and bcrypt helper function work in the same way
I have a problem when decrypting passwords hashed with bcrypt. I can't login when I use this code. So, are there any mistakes?
function login(){
if ($this->session->userdata('username'))
{
redirect('dasbor');
}
//fungsi login
$valid = $this->form_validation;
$username = $this->input->post("username");
$password = $this->input->post("password");
$hash = $this->db->get('users')->row('password');
$hashp = $this->bcrypt->check_password($password,$hash);
$valid->set_rules("username","Username","required");
$valid->set_rules("password","Password","required");
if ($hashp) {
if($valid->run()) {
$this->simple_login->login($username,$hashp, base_url("dasbor"), base_url("Auth/login"));
}
}
// End fungsi login
$data = array('title'=>'Halaman Login Admin');
$this->load->view('admin/login_view',$data);
}
please help me to solve this problem.
I know this is an old question, but I want to help others who face the same problem.
First thing first, you need to rework again on your algorithm. The password_verify() function needs 2 parameters:
Password, the text that the user input in the text field before submitting the form.
Hash, a hash that is already stored in your database.
The goal is to verify if Password and Hash are similar. As you know, the password_hash() will return a different result at different times even when you hash the same string. Because of that, you can not use this->db->where() active record.
So, what I would do are these simple 2 steps:
Create a function in the model (e.g. Main_model.php) for getting user data.
public function get_user($user) {
$this->db->where('username', $user);
return $this->db->get('user')->row_array();
}
Get the password from the controller and use password_verify
$get_user = $this->main_model->get_user($this->input->post('username'));
if(password_verify($this->input->post('password'), $get_user['password'])){
// Success
}
else {
// Not Success
}
And one additional tip from me, don't write any active record in the Controller. It is not neat for the MVC method.
I'm currently using codeIgniter 3. I created a registration page with username, password, password confirmation and email. For compare the two string, I used strcmp() function. Now, the problem is when I put something like
password = "moon";
confirmation_password = "moon";
It work without any problems. Logically you'll tell me :)
Otherwise, when I put something like
password = "moon";
confirmation_password = "something else";
Now it still work with show me the appropriate error message. Logically again you'll tell me. Except that another error message pop:
Unable to access an error message corresponding to your field name Password confirmation.(check_information)
I don't understand how this error message could pop only when the confirmation_password variable doesn't match with password variable.
Here's my code
function index()
{
$this->form_validation->set_rules('confirmation_password', 'Password confirmation', 'trim|required|callback_check_information');
}
function check_information($confirmation_password)
{
$password = $this->input->post('password');
if (strcmp($password, $confirmation_password))
{
echo 'password and confirmation password doesn\'t match';
return FALSE;
}
}
Does anyone can tell if is there something wrong in my code ?
I voluntarily show you a part of my code for avoid to make my post too long.
Thanks
You have to return with boolean in both cases, and not echo the message, set it:
function check_information($confirmation_password)
{
$password = $this->input->post('password');
if (strcmp($password, $confirmation_password))
{
$this->form_validation->set_message('check_information', 'password and confirmation password doesn\'t match');
return FALSE;
}
else {
return TRUE;
}
}
There is a simple solution, try this:
$this->form_validation->set_rules('confirmation_password', 'Password Confirmation', 'required|matches[password]');
i use tank auth as login handler in code igniter. when i use the forget password feature, i get a link send by mail http://xx.xx.xx/en//auth/reset_password/2/01b951fd2a02efa2d64f1fe70c2a4e3b. When i click this link it always says: "Your activation key is incorrect or expired. Please check your email again and follow the instructions."
i changed the segments so it gets the right segments but somehow it the goes wrong on if ($this->form_validation->run()). it Somehow wants the new_password and confirm_new_password as post data but from the link in the email no post data will ofcourse be sent.
Is this a bug in tank auth, is there a quickfix (does tank_auth forget a step, is something not configured right?)
reference code:
function reset_password()
{
$break =$this->uri->total_segments();
$new_pass_key= $this->uri->segment($break);
$user_id= $this->uri->segment($break-1);
$this->form_validation->set_rules('new_password', 'New Password', 'trim|required|xss_clean|min_length['.$this->config->item('password_min_length', 'tank_auth').']|max_length['.$this->config->item('password_max_length', 'tank_auth').']|alpha_dash');
$this->form_validation->set_rules('confirm_new_password', 'Confirm new Password', 'trim|required|xss_clean|matches[new_password]');
$data['errors'] = array();
if ($this->form_validation->run()) { //breaks here. For some reason wants to validate post data which
if (!is_null($data = $this->tank_auth->reset_password($user_id, $new_pass_key,$this->form_validation->set_value('new_password')))) { // success
$data['site_name'] = $this->config->item('website_name', 'tank_auth');
// Send email with new password
$this->_send_email('reset_password', $data['email'], $data);
$this->_show_message($this->lang->line('auth_message_new_password_activated').' '.anchor('/auth/login/', 'Login'));
} else { // fail
$this->_show_message($this->lang->line('auth_message_new_password_failed'));
}
} else {
// Try to activate user by password key (if not activated yet)
if ($this->config->item('email_activation', 'tank_auth')) {
$this->tank_auth->activate_user($user_id, $new_pass_key, FALSE);
}
if (!$this->tank_auth->can_reset_password($user_id, $new_pass_key)) {
$this->_show_message($this->lang->line('auth_message_new_password_failed'));
}
}
$this->load->view('auth/reset_password_form', $data);
}
Your new_pass_key and $user_id are wrong I guess.
It should work out of the box with this:
$user_id = $this->uri->segment(3);
$new_pass_key = $this->uri->segment(4);
EDIT:
$user_id = $this->uri->segment(4);
$new_pass_key = $this->uri->segment(5);
Why did you change that by the way?
I have the following function in a CakePHP 1.3 app that takes a token and allows the user to change their password. Everything seems to work fine except that the password doesn't actually get changed :/ Any ideas what the problem is?
function admin_changepassword ( $token = null )
{
// If has a token or form has been submitted
if (!empty($token) || !(empty($this->data)))
{
$user = $this->User->find('first',array("MD5(User.email + '".Configure::read('Security.salt')."')"=>$token));
if (empty($user))
{
$this->redirect(array('admin'=>false,'controller'=>'pages','action'=>'display','home'));
$this->Session->setFlash('Invalid token');
}
else
{
$this->set('user',$user);
if (!empty($this->data['User']['password']))
{
$user['User']['password'] = $this->data['User']['password'];
$this->User->save($this->data);
$this->Session->setFlash('Your password has been changed! Please log in.');
$this->redirect(array('admin'=>true,'controller' => 'users', 'action' => 'login'));
}
}
}
else
{
$this->redirect(array('admin'=>false,'controller'=>'home','action'=>'display','home'));
$this->Session->setFlash('No token');
}
}
Personally I'd do something like this; but I'm assuming your user is actually logged in, using the auth component or similar. Untested; but logic looks like it should work to me.
<?php
function admin_changepassword ($token = NULL) {
// bail out early if there is no token set, and always set the flash before redirecting.
if($token==NULL) {
$this->Session->setFlash('No token');
$this->redirect(array('admin'=>false,'controller'=>'home','action'=>'display','home'));
}
// this is an admin action; the user already be logged in right?
$this->User->id = $this->Auth->user('id');
$user_password = $this->User->field('password');
// does the token match the hashed password, and did they enter a new password?
if($token==md5($user_password . Configure::read('Security.salt')) && !empty($this->data['User']['password'])) {
$this->User->saveField('password', $this->data['User']['password']);
$this->Session->setFlash('Your password has been changed! Please log in.');
$this->redirect(array('admin'=>true,'controller' => 'users', 'action' => 'login'));
}
// somethings gone wrong/password was not updated
$this->Session->setFlash('Your password was not changed.');
$this->redirect(array('admin'=>false,'controller'=>'home','action'=>'display','home'));
}
OK upon some testing, your problem is as I initially suggested in my comment.
You aren't setting the id of your user, so:
$this->User->save($this->data);
is not updating the password, it is adding a new row to your database.
You need to specify the ID of the user's to update.
$user = $this->User->find('first',array("MD5(User.email +
'".Configure::read('Security.salt')."')"=>$token));
// this line is redundant
$user['User']['password'] = $this->data['User']['password'];
$this->User->id = $user['User']['id']; // set user id
$this->User->save($this->data); // save it
If you check your users table I suspect you will find there are lots of empty records with the "changed" password. My testing agrees with the cake manual.
This is an old thread, but it might help someone
function changePwd(){
$this->User->id = $this->data->['User']['id']; //assuming this is set
//check if the password fields are empty
//check if the password fields match (password and confirm password one)
//convert password
$this->request->data['User']['password'] = $this->Auth->password($this->data['User']['password'] );
//saveField worked for me
if($this->User->saveField('password',$this->request->data['User']['password'])){
$this->Session->setFlash('Password changed successfully.','flashSuccess');
}else{ ....
}