I am kind of newbie around here so hope i am doing fine what am i doing.
I started working with Codeignter recently and trying to build a secured login to restrict access from three devices only.
On login
I am trying to add a never-expiring "device_id" cookie upon successful authentication. That cookie would be a a unique string and store it into database
And if the user has aleady three devices stored to be rejected.
If the user has available devices slots, this to be recorded and added to its stack.
Basicly i want to allow access if the user has avail slots or the cookie arleady exists.
Have any ideea where should i start or there is a Codeigniter library ?
The code from my control that alows and valides login is:
function login()
{
if ($this->session->userdata('logged_in'))
{
$logged_in_user = $this->session->userdata('logged_in');
if ($logged_in_user['is_admin'])
{
redirect('admin');
}
else
{
redirect(base_url());
}
}
// set form validation rules
$this->form_validation->set_error_delimiters($this->config->item('error_delimeter_left'), $this->config->item('error_delimeter_right'));
$this->form_validation->set_rules('username', lang('users input username_email'), 'required|trim');
$this->form_validation->set_rules('password', lang('users input password'), 'required|trim|callback__check_login');
if ($this->form_validation->run() == TRUE)
{
if ($this->session->userdata('redirect'))
{
$redirect = $this->session->userdata('redirect');
$this->session->unset_userdata('redirect');
redirect($redirect);
}
else
{
$logged_in_user = $this->session->userdata('logged_in');
if ($logged_in_user['is_admin'])
{
redirect('admin');
}
else
{
redirect(base_url());
}
}
}
// setup page header data
$this->add_css_theme( 'login.css' );
$this->set_title( lang('users title login') );
$data = $this->includes;
// load views
$data['content'] = $this->load->view('user/login', NULL, TRUE);
$this->load->view($this->template, $data);
}
it's not a good idea to write your system ....you can not secure your auth system from session hijacking (when session_id not change in long period) , dos attack , ddos attack , etc very easliy .... it's better to use early written system like auth_ion ....
you can find authentication library for code igniter in :
https://github.com/bcit-ci/CodeIgniter/wiki/Contributions#libraries
i preffer ion_auth in that list ...
Related
I am trying to unset my current logged in user's session.It's working fine if i am doing normal login but when i use remember me settings using cookies it's not being destroy.
My code for set the session and cookie is
public function login() {
if(isset($this->session->userdata['username']) || isset($_COOKIE['user_id'])){
$this->load->model('User');
$p_uid = $this->User->user_login($_COOKIE['user_id'], $_COOKIE['password']);
redirect(base_url() . "dashboard");
}else{
$this->form_validation->set_rules('user_id', 'User ID', 'required');
$this->form_validation->set_rules('password', 'Password', 'required');
if ($this->form_validation->run() == FALSE) {
$this->load->view('login/login');
} else {
$user_id = $this->input->post('user_id');
$password = $this->input->post('password');
$this->load->model('User');
$p_uid = $this->User->user_login($user_id, $password);
//var_dump($p_uid);
if ($p_uid) {
if(isset($_POST['remember_me'])){
setcookie("user_id",$user_id,time()+86400*30);
setcookie("password",$password,time()+86400*30);
}
redirect(base_url() . "dashboard/");
} else {
$data=array(
"error"=>"Wrong Userid Or Password"
);
$this->load->view('login/login',$data);
}
}
}
}
And My logout Function is:
public function logout(){
$this->load->helper('cookie');
delete_cookie("user_id");
delete_cookie("password");
$this->session->unset_userdata("username");
$this->session->sess_destroy();
redirect(base_url());
}
Where i am doing mistake. please help. Thanks
First of all, your remember-me mechanism is seriously flawed. See Implementing Secure User Authentication in PHP Applications with Long-Term Persistence.
I don't understand how your login works. You are checking if username is set in session, then are using cookies to perform login. I guess you've made it work as the first part of || always fails since $this->session->userdata['username'] will never be set. The correct way to access username from session would be:
$_SESSION['username']
OR
$this->session->userdata('username')
OR
$this->session->username
Finally, make sure the cookies are actually being deleted by inspecting your requests in network tab. Codeigniter deletes cookies by setting a negative expiration time of around a day, see if this is the case in your version of Codeigniter. For best results, just set the cookie again with large negative expiration time, and instead of checking if cookie is set, check if cookie is !empty.
I've faced the same issue a while ago. I was trying all methods which were possible. But I failed. Finally I found the solution with ob_start and ob_clean . Logout should be like this:
class controllerName extends CI_Controller
{
function __construct()
{
parent::__construct();
ob_start();
$this->load->library('Session');
$this->load->helper('cookie');
}
public function logout()
{
$this->load->driver('cache');
$user_id = array(
'name' => 'user_id',
'value' => '',
'expire' => '0',
'domain' => '.localhost',
'prefix' => ''
);
delete_cookie($user_id);
$this->session->sess_destroy();
$this->cache->clean();
ob_clean();
redirect(base_url());
}
}
To prevent browser back button previous page load, you should do something like this
$sess = $this->session->userdata('username');
if(empty($sess))
{
$this->session->set_flashdata('error', 'Session has Expired. Please login');
redirect('loginController/method');
}
else
{
# success.
# continue the normal code here
}
FYI: This should be added in every function or being used by a constructor to do it.
NOTE : Don't add password in cookie. Read - php cookie injection vulnerability?
To unset single element from session array:
$this->session->unset_userdata('some_name');
You can pass an array of keys to unset multiple values:
$array_items = array('username' => '', 'email' => '');
$this->session->unset_userdata($array_items);
public function check_admin_login()
{
$admin_email_address=$this->input->post('admin_email_address',true);
$admin_password=$this->input->post('admin_password',true);
$this->load->model('admin_model','a_model');
$result= $this->a_model->check_admin_login_info($admin_email_address,$admin_password);
// echo '<pre>';
// print_r($result);
// exit();
$sdata=array();
if($result)
{
$sdata['full_name']=$result->admin_full_name;
$sdata['admin_id']=$result->admin_id;
$this->session->set_userdata($sdata);
//$sdata[]
redirect('super_admin');
}
else{
$sdata['message']='Your User Id / Password Invalide !';
$this->session->set_userdata($sdata);
$this->load->view('admin/admin_login');
}
}
for login and for logout
public function logout()
{
$this->session->unset_userdata('full_name');
$this->session->unset_userdata('admin_id');
$sdata=array();
$sdata['message']='You are Successfully Logout !';
$this->session->set_userdata($sdata);
redirect('admin');
}
This will happen when login page in http or localhost then codeigniter create session for http or locahost.
when we are trying get session in https://www.example.com or http://[::1]/ then the session will not added for these type of urls..
try to use one type of url pattern in website
For delete cookie
delete_cookie('name', $domain, $path);
For delete/destroy sesstion
$this->session->sess_destroy();
To destroy a particular session
$this->session->unset_userdata('name');
For multiple items
$items = array('item-name1' => '', 'item-name2' => '');
$this->session->unset_userdata($items);
I have just installed codoforum (https://codoforum.com)
and want to use this feature https://codoforum.com/documentation/implementing-codoforum-sso
which consist of integrating Single Sign on in my website.
The website I which to integrate the forum into it is using Yii 1 Framework, I am not familiar with it unfortunately.
Following the documentation of codoforum, I filled in the configuation form and enabled the SSO plugin, what I should do now is complete the file client.php here : https://github.com/evnix/codoforum-sso.
Especially those lines :
if (USER_IS_LOGGED_IN) {
$account['uid'] = USERID; //Your logged in user's userid
$account['name'] = USERNAME; //Your logged in user's username
$account['mail'] = EMAILID; //Your logged in user's email id
$account['avatar'] = ''; //not used as of now
}
I filled in those filled manually and it worked, It detects if I am already connected to yii1 website and connect me to the forum using the email I provided.
What I want now is to get those information using the session, I put the file clien.php in the root of my website mywebsite.com/client.php
I have done some research and I found that this method in siteController is responsible for logging :
public function actionLogin() {
$model = new LoginForm;
// if it is ajax validation request
if (isset($_POST['ajax']) && $_POST['ajax'] === 'login-form') {
echo CActiveForm::validate($model);
Yii::app()->end();
}
// collect user input data
if (isset($_POST['LoginForm'])) {
$model->attributes = $_POST['LoginForm'];
// validate user input and redirect to the previous page if valid
if ($model->validate() && $model->login()) {
if (Yii::app()->session['type'] == 1 ) {
$this->redirect(Yii::app()->homeUrl . 'administration/team');
}else if (Yii::app()->session['type'] == 2 ) {
$this->redirect(Yii::app()->homeUrl . 'agenda');
} else {
$this->redirect(Yii::app()->homeUrl);
}
}
}
// display the login form
$this->render('login', array('model' => $model));
}
I have tried to add this code :
session_start();
$_SESSION['username']=$model->username;
(after : if ($model->validate() && $model->login()))
and use $_Session in the file client.php but it didn't work.
The problem is that I have no idea how yii1 framework work, and it will take me sometime to be familiar with it, I know that there is session in Yii1, but I don't know how to use it and where to put the file client.php and how can I make it detect the Yii Session.
But if I can use the global session it would be better.
Thank you so much for your time and your answer.
I've got a small problem with my smarty project, logout problem to be precise. I have a index.php page which is the "main" page and it gets POST data and directs actions based on current data. There`s checking if the session variables has been set. Now when I login I have function like this:
function login($value)
{
$res = $this->sql->checkLogin($value);
if($res)
{
//checks if user is admin
$isadm = $this->sql->isAdm($value);
if($isadm == true)
{
$_SESSION['user'] = $value['name'];
$_SESSION['adm'] = true;
$message = 'Admin';
$this->tpl->assign('var', $message);
if($_SESSION['adm'] == true)
{
//sets some variables for admin users
$navigation = 'navi';
$this->tpl->assign('navigation', $navigation);
}
$this->tpl->display('maint_main.tpl');
}
//user is not admin
else
{
$_SESSION['user'] = $value['name'];
$_SESSION['adm'] = false;
$message = 'Perus';
$this->tpl->assign('var', $message);
if($_SESSION['adm'] == true)
{
$navigation = 'navi';
$this->tpl->assign('navigation', $navigation);
}
$this->tpl->display('maint_main.tpl');
}
}
//login failes, show login form and info
else
{
$message = 'Login failed';
$this->tpl->assign('var', $message);
$this->tpl->display('login_form.tpl');
}
}
and logout function :
function logout()
{
setcookie(session_name(), '', time()-42000, '/');
session_unset();
session_destroy();
$this->tpl->display('login_form.tpl');
}
These work just about the way they are supposed to but the real problem occurs when I log out and redirect to the login_form.tpl. If I use the back button of the browser the POST data with username and password is retrieved and the login goes through again. This causes that those pages behind login are still viewable. As I am not quite familiar with Smarty yet I couldn`t figure out any way to fix this. So basically how to prevent access to that POST data after logout?
I don't think this has anything to do with smarty. This is a browser/http generic issue. Most browsers will re-post form data after confirmation from the user.
One approach to make re-posts of the form invalid would be to pass along a secret code/token (perhaps a guid or your session id) which is also stored in session data. When the user logs out, clear their session (or at least the secret code you're checking). When the user logs in, check to make sure that the confirmation code matches the one for the current session.
This pattern is often used to manage csrf attacks and is often known as a 'synchronizer token'. This blog post provides a good explanation https://blog.whitehatsec.com/tag/synchronizer-token/
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 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.