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?
Related
I have an installation of Codeigniter, IonAuth + Hybridauth which I am reworking so my users can choose their own username instead of generating one using the first and last names returned by facebook.
So in my code below I check to see if a username was posted, if not I want to load the choose_username view but for some reason the view is not loading and its completely skipping that section which is why I added die('Why no view')
Update: This first piece of code runs fine in a new controller
Checkout the code here:
if(isset($_POST['username'])){
$username = $this->input->post('username', TRUE);
die($username);
}else{
$this->data['message'] = 'Please choose a username.';
$this->data['template'] = 'guests/partials/choose_username';
$this->load->view('guests/template/standard', $this->data);
die('Why no view?');
};
Longer version:
function login_provider($provider = '')
{
if(empty($provider)) redirect();
try
{
// create an instance for Hybridauth with the configuration file
$this->load->library('HybridAuthLib');
if ($this->hybridauthlib->serviceEnabled($provider))
{
// try to authenticate the selected $provider
$service = $this->hybridauthlib->authenticate($provider);
if ($service->isUserConnected())
{
// grab the user profile
$user_profile = $service->getUserProfile();
////////////
//var_dump($user_profile);
//die();
////////////
$provider_uid = $user_profile->identifier;
if($this->ion_auth->login_by_provider($provider,$provider_uid))
{
$data['user_profile'] = $this->ion_auth->user_by_provider();
//$this->load->view('auth/user_profile',$data);
$user = $this->ion_auth->user()->row();
//Redirect to custom subdomain
$url = explode('://',site_url());
if (strpos(site_url(),$user->username) !== false) {
redirect($url[0].'://'.str_replace('www','',$url[1]).'dashboard','refresh');
}
else{
redirect($url[0].'://'.$user->username.str_replace('www','',$url[1]).'dashboard');
};
}
else
{ // if authentication does not exist and email is not in use, then we create a new user
//Check if username was posted
if(isset($_POST['username'])){
$username = $this->input->post('username', TRUE);
die($username);
}else{
$this->data['message'] = 'Please choose a username.';
$this->data['template'] = 'guests/partials/choose_username';
$this->load->view('guests/template/standard', $this->data);
die('Why no view?');
};
So when I run the above code, all i get is a blank page with: Why no view.
As above, usually when I run into this sort of issue it's from a bug in the view code.
Also, I don't know what, is actually being passed by this post in the event of there not being username data but you might want to also be checking for an empty value for username. This is probably not the issue but it would be good to confirm that the initial if is evaluating the way you expect.
I am building a social network via code igniter. Upon registration, the potential member get's stored in the db, and their status get's marked to pending. I then send them a confirmation email with a hashed token link. When they hit the link it marks their account as active and takes them to a welcome page that has a sign in.
When I go to the link it sets of an infinite loop and freezes my computer when I'm working on my MAMP. ( or I'm suspicious that it's an infinite loop )
Here is my pertinent code:
auth CONTROLLER that sends the email:
function varification_email()
{
$query = $this->db->query('SELECT * FROM users order by id desc LIMIT 1');
$token = sha1($user->email.$user->salt).dechex($user->id);
$domain = "clci.dev/index.php";
$link = "http://www.".$domain."/account/confirmation/?token=$token";
foreach ($query->result() as $user)
{
$this->load->library('email');
$this->email->from('noreply#cysticlife.org', 'CysticLife');
$this->email->to($user->email);
$this->email->subject('Welcome to CysticLife!');
$this->email->message("Thanks for signing up for CysticLife! To complete the registration process please go to the following web address:\n\n$link\n\n-Your friends at CysticLife\n\nPlease remember to add the cysticlife.org domain to your address book to ensure that you receive your CysticLife e-Notifications as requested.eh");
$this->email->send();
}
account CONTROLLER that the user is linked back to from the email:
public function confirmation() {
$data['main_content'] = 'account/confirmation';
$this->load->view('includes/templates/main_page_template', $data);
$this->load->library('encrypt');
$this->load->helper('url');
$this->load->library('session');
$this->load->model('user_model', 'um');
$login = $this->input->post('submit');
//IF THE SUBMIT BUTTON IS TRIGGERED THE POST DATA IS SENT TO THE VALIDATE FUNCTION IN THE MODEL VIA VARIABLES CREATED
if($login) {
$user = $this->um->validate(array('email' => $this->input->post('email')));
if( $user ) {
// CHECK THE USER'S PASSWORD AGAINST THE ONE FROM THE LOGIN FORM
if($user->password == $this->encrypt->sha1( $user->salt . $this->encrypt->sha1($this->input->post('password')))) {
$this->session->set_userdata('logged_in', TRUE);
$this->session->set_userdata(array(
'email' => $this->input->post('email')
));
$this->session->userdata('logged_in');
redirect('account/dashboard');
exit;
}
}
}
$this->index();
}
Thanks in advance
varification_email()
In varification_email(), $user is used before it is defined. I assume the real code doesn't have this issue.
Your method for selecting the user in the DB in prone to concurrency errors (wrong user returned).
confirmation()
I already had encountered browser hangs because of too large cookies, exceeding something like 4 kB. Have a look at that.
The problem might be in user_model->validate(). Comment out the following of the code and check if it works.
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
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{ ....
}
How can I verify an email address with codeigniter? I just went through the manual, I couldn't find this.
With email verification, i mean the exact same verification you see when registering on a community forum.
Thanks in advance!
Use the Email Class to send the email. The email could contain a link with a "secret key", something random and hash-like, like 5dfg7898ssdf (I made that one up :) ). The link could point to: example.com/verify/user/5dfg7898ssdf Then in a codeigniter controller called "verify", you put this function (just some quick code):
function user($key = NULL)
{
if($key)
{
// Find key in database
// If it exists, then mark
// the corresponding user as "activated"
}
}
function verify($verificationText=NULL){
$noRecords = $this->HomeModel->verifyEmailAddress($verificationText);
if ($noRecords > 0){
$error = array( 'success' => "Email Verified Successfully!");
}else{
$error = array( 'error' => "Sorry Unable to Verify Your Email!");
}
$data['errormsg'] = $error;
$this->load->view('index.php', $data);
}