PHP $_SESSION AND $_COOKIE Strange behavior - php

I'm trying to install COOKIES into my website.
I have found a script on GitHub: https://github.com/jotaroita/secure-login-php7-remember-register-resetpw
I have implemented the script and i'm able to login.
I'm able to login with just SESSION, or i can login with both SESSION and set a "Remember me -COOKIE".
To test the COOKIE i have set the SESSION to expire after 1 minute. $expireAfter = 1;
Senario:
I login to the website and check "remember me". Session starts and a cookie is set. Everything fine!
## last action: 1 seconds ago
skip the cookie check: session already set
I wait 60 seconds and reloads the page. Sessions destroys and Cookie reads:
## last action: 108 seconds ago
session destroy for inactivity
cookie read
cookie valid format
cookie right selector
cookie right token
set a new token in DB and in cookie
session set <- Within this message i can output Session data: $_SESSION['user'] at all times
BUT in my other page(home.php) $_SESSION['user'] is empty?! (I include the SESSION and COOKIE check from: check.php) if(isset($_SESSION['last_action'])){ returns true
If i wait another 60 seconds and reload the page if(isset($_SESSION['last_action'])){ returns false. But now the $_SESSION['user'] is set.
If i wait another 60 seconds and reload the page. if(isset($_SESSION['last_action'])){ returns true. But now the $_SESSION['user'] is empty.
home.php
<?php
//START SESSION
session_start();
//CONNECT TO DB, SET HEADER, SET TIMEZONE, CHECK FOR LOGIN-COOKIES
include("check.php");
//CHECK IF SESSION EXIST
if(!isset($_SESSION['user'])) {
$isSesstion = false;
header("Location: /index.php");
}
else{
$isSesstion = true;
}
.....
check.php
<?php
define ("PEPPER",''); //random string for extra salt, use if you want.
define ("WEBSITE",'mydomain.com'); //your web site without http:// without final /
define ("SCRIPTFOLDER",'/login'); //direcory of the script start with a / if you installed the script in the root write just a / never finish with a /
$hosting="localhost"; //your host or localhost
$database="db"; //your database name
$database_user="user"; //your username for database
$database_password="pwd"; //your database password
require_once('pdo_db.php');
//generate random sequence or numbers and letter avoid problems with special chars
function aZ ($n=12) {
$chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$bytes = random_ver($n);
$result="";
foreach (str_split($bytes) as $byte) $result .= $chars[ord($byte) % strlen($chars)];
return $result;
}
//generate random and avoid compatibility problem with php version
function random_ver ($n=10) {
$v=(int)phpversion()+0;
if ($v<7) {
//if php version < 7 use the old function for generate random bytes
return openssl_random_pseudo_bytes($n);
}else{
//random_bytes is better but works only with php version > 7
return random_bytes($n);
}
}
// ********************************
// * SESSION TIME UPDATE *
// ********************************
//Expire the session if user is inactive for 15 minutes or more.
//if u want to check how cookie works let the session id expire (wait X minutes without action, maybe set expireAfter to low value),
//close the browser then open again
$expireAfter = 1;
//Check to see if our "last action" session
//variable has been set.
if(isset($_SESSION['last_action'])){ echo 'IN';
//Figure out how many seconds have passed
//since the user was last active.
$secondsInactive = time() - $_SESSION['last_action'];
//Convert our minutes into seconds.
$expireAfterSeconds = $expireAfter * 60;
//Check to see if they have been inactive for too long.
$debug.="last action: $secondsInactive seconds ago<br>";
if($secondsInactive >= $expireAfterSeconds){
//User has been inactive for too long.
//Kill their session.
session_unset();
session_destroy();
$debug.="session destroy for inactivity<br>";
}
}
//Assign the current timestamp as the user's
//latest activity
$_SESSION['last_action'] = time();
// *********************************
// * CHECK AUTO LOG-IN WITH COOKIE *
// *********************************
//if session is not set, but cookie exists
if (empty($_SESSION['user']) && !empty($_COOKIE['remember']) && $_GET["logout"]!=1) {
$debug.="cookie read<br>";
list($selector, $authenticator) = explode(':', urldecode($_COOKIE['remember']));
//get from database the row with id and token related to selector code in the cookie
$sql = $db->prepare("SELECT * FROM user_tokens
WHERE selector = ? limit 1");
$sql->bindParam(1, $selector);
$sql->execute();
$row = $sql->fetch(PDO::FETCH_ASSOC);
if (empty($authenticator) or empty($selector))
$debug.="cookie invalid format<br>";
//continue to check the authenticator only if the selector in the cookie is present in the database
if (($sql->rowCount() > 0) && !empty($authenticator) && !empty($selector)) {
$debug.="cookie valid format<br>";
// the token provided is like the token in the database
// the functions password_verify and password_hash add secure salt and avoid timing attacks
if (password_verify(base64_decode($authenticator), $row['hashedvalidator'])){
//SET SESSION DATA
$sql = $db->prepare("SELECT * FROM users WHERE id = ?");
$sql->bindParam(1, $row['userid']);
$sql->execute();
$session_data = $sql->fetch(PDO::FETCH_ASSOC);
//UNSET VARS
unset($session_data['password']);
$_SESSION['user'] = $session_data;
//update database with a new token for the same selector and set the cookie again
$authenticator = bin2hex(random_ver(33));
$res=$db->prepare("UPDATE user_tokens SET hashedvalidator = ? , expires = FROM_UNIXTIME(".(time() + 864000*7).") , ip = ? WHERE selector = ?");
$res->execute(array(password_hash($authenticator, PASSWORD_DEFAULT, ['cost' => 12]),$_SERVER['REMOTE_ADDR'],$selector));
//set the cookie
$setc = setcookie(
'remember',
$selector.':'.base64_encode($authenticator),
time() + 864000*7, //the cookie will be valid for 7 days, or till log-out (if u want change it, modify the login.php file too)
'/',
WEBSITE,
false, // TLS-only set to true if u have a website on https://
false // http-only
);
$debug.="cookie right selector<br>cookie right token<br>set a new token in DB and in cookie<br>session set ".$_SESSION['user']['usr_fname']."<br>";
} else {
//selector exists but token doesnt match. that could be a secure problem, all selector/authenticator in database for that user will be deleted
$res=$db->prepare("DELETE FROM user_tokens WHERE userid = ".$row["userid"]);
$res->execute();
$debug.="cookie right selector<br>cookie wrong token (all DB entry for that user are deleted)<br>";
}
} else {
$debug.="selector not found in DB<br>";
}
} else {
$debug.="skip the cookie check: ";
if (!empty($_SESSION['user'])) $debug.="session already set<br>";
if (empty($_COOKIE['remember'])) $debug.="no cookie set<br>";
}
?>
So, whats wrong with the code?
Why is the $_SESSION filled with data every second time i refresh the webpage?
Why doesn't if(isset($_SESSION['last_action'])){ returns true everytime i refresh the page? And why does $_SESSION carry data in the debug message session set ".$_SESSION['user']['usr_fname']." all the time... but it is not carried over to home.php with the include(check.php"); ?
Do you need some more code? Just ask for it!

I think i found the problem.
After unset & destroy the session. I had to start a new session.
Strange thing this only happens every second time. But adding session_start(); solved the problem!
if(isset($_SESSION['last_action'])){
$secondsInactive = time() - $_SESSION['last_action'];
$expireAfterSeconds = $expireAfter * 60;
$debug.="last action: $secondsInactive seconds ago<br>";
if($secondsInactive >= $expireAfterSeconds){
//User has been inactive for too long.
//Kill their session.
session_unset();
session_destroy();
$debug.="session destroy for inactivity<br>";
}
}
...
session_start();
$_SESSION['user'] = $session_data;
...

Related

Destroy PHP sessions by downtime

When you access the system, it generates a session as below:
session_start();
$_SESSION['Logged'] = time();
$_SESSION['Limit'] = 900; // 15 minutes
And when it exits the system, the session is destroyed.
The problem is when the user leaves the system without clicking the exit link and yes directly through the browser. How do I destroy the session by downtime? I tried the code below, but how do I know it's no longer in the system? It is necessary to change the status of the database and closing the system by the browser, I can not change.
session_start();
if($_SESSION['Logged'])
{
$seconds = time()- $_SESSION['Logged'];
}
if($seconds > $_SESSION['Limit'])
{
mysqli_query($this->conexao,"UPDATE table_admin SET StatusAdmin = 0 WHERE IdUser = '".$id."';");
session_destroy();
}
I'm sorry about my English.

Logout user after a specific time of inactivity

I am creating a website with more than 10 different php files. I want to check if the user is inactive, starting from the login page. So, if a user logs in and remains idle for a specific period of time, it has to log that user out. I am new to PHP and am currently using an answer to similar question which is
if (isset($_SESSION["LAST_ACTIVITY"])) {
if (time() - $_SESSION["LAST_ACTIVITY"] > 1800)) {
// last request was more than 30 minutes ago
session_unset(); // unset $_SESSION variable for the run-time
session_destroy(); // destroy session data in storage
} else if (time() - $_SESSION["LAST_ACTIVITY"] > 60) {
$_SESSION["LAST_ACTIVITY"] = time(); // update last activity time stamp
}
}
I found the answer here:
expire session when there is no activity in PHP
I have created a separate page called session.php and pasted the code in the above link. Then I included the file session.php in my login page (which checks for the credentials entered and logs a user in). The problem is, the if loop is not being run and I do not know how to define $_SESSION['LAST_ACTIVITY'] variable. I used the following in my login page:
$query = "SELECT *
FROM user_details
WHERE username = '$username'
AND password = '$password'";
$result = mysqli_query($dbconnect, $query);
$row = mysqli_fetch_array($result);
$count = mysqli_num_rows($result);
if ($count == 1) {
session_start();
echo "Welcome " .$username. "</br>";
$_SESSION['username'] = $username;
$login_time = time();
$_SESSION["LAST_ACTIVITY"] = $login_time ;
include('session.php');
I also tried including session.php at the beginning of the file but of no use. The problem is: time() - $_SESSION["LAST_ACTIVITY"] is being equalled to 0. How do I store last activity time and compare it with the current time? Also, should I include session.php in every other webpage file for the website to check user activity ? If yes, should I include it at the beginning or at the end ?
This code will solved your problem for session timeout.
<?php
// set timeout period in seconds
$inactive = 60; //after 60 seconds the user gets logged out
// check to see if $_SESSION['timeout'] is set
if(isset($_SESSION['timeout']) ) {
$session_life = time() - $_SESSION['timeout'];
if($session_life > $inactive)
{
session_destroy();
header("Location: Logout.php");
}
}
$_SESSION['timeout'] = time();
?>

Set Session Timeout

I have a single form for login for both admin and general users. I would like to time the sessions out after 30 minutes how would I amend my current code to do that?
<?php
session_start(); //Start the session
define(ADMIN,$_SESSION['username']); //Get the user name from the previously registered super global variable
if(!session_is_registered("admin")){ //If session not registered
header("location:../index.php"); // Redirect to login.php page
}
?>
Here is the code to clear the session for a specified time.
To clear the inactive session, you have to renew the session timeout every page.
Hope it helps.
For reference, http://bytes.com/topic/php/insights/889606-setting-timeout-php-sessions
session_start();
$timeout = 60; // Number of seconds until it times out.
// Check if the timeout field exists.
if(isset($_SESSION['timeout'])) {
// See if the number of seconds since the last
// visit is larger than the timeout period.
$duration = time() - (int)$_SESSION['timeout'];
if($duration > $timeout) {
// Destroy the session and restart it.
session_destroy();
session_start();
}
}
// Update the timout field with the current time.
$_SESSION['timeout'] = time();
Via the runtime configuration item session.cookie_lifetime or function session_set_cookie_params()
if ($_SESSION['timeout'] + 30 * 60 < time()) {
// 30 min timeout
}

Deleting a PHP cookie upon user logout

I started creating a login system which utilised cookies for a "remember me" feature. All is working fine however I am having trouble deleting the cookie upon user logout.
If a user does not check the "remember me" box and logs in successfully I.e. does not create the cookie, the logout function works as expected and loads the login box.
If they don't do the latter and the user clicks the logout button the cookie remains and it shows they are still logged in.
If someone could shine some light as to why the cookie wont delete I would be very grateful.
Below is the code I am using:
PHP code that runs after a user tries to log in:
// If the form has been submitted
if(isset($_POST['login'])):
// Protect from unwanted code/string context
$username = strip_tags(addslashes(trim($_POST['username'])));
$string = strip_tags(addslashes(trim($_POST['password'])));
$remember = strip_tags(addslashes(trim($_POST['remember'])));
// Pass the returned variables from functions to a local versions
$password = salting($string); // Salt Password Preperation
$link = db_connect(); // DB connection
// Connect to the database and try to find a login match
$result = mysqli_query($link,"SELECT * FROM web_users WHERE username='".$username."' AND password='".$password."'");
$row = mysqli_fetch_object($result);
// Create erronous results if submitted data is invalid
if (mysqli_num_rows($result) !== 1):
$errmsg[0] = "Invalid Username or Password, please re-try";
endif;
$e_login = serialize($errmsg);
// If validation passes then continue
if (!$errmsg):
// Increment the login_count field by 1
$row->login_count++;
$count = $row->login_count;
// Retrieve the date for admin purposes
$date = date('Y-m-d-h:i:s'); // Y=year (4 digits) m=month (leading zero) h=hour i=minutes s=seconds
// Salt Password Preperation
$string = session_id();
$login_id = salting($string);
// Connect to the database and update the related row
$update = mysqli_query($link,"UPDATE web_users
SET login_count='".$count."',
login_last='".$date."',
login_id='".$login_id."',
logged='1'
WHERE id='".$row->id."'")
or die(mysqli_error($link));
// Create a multi-dimensional session array
$_SESSION['login'] = array('user' => $row->display_name,
'id' => $row->id,
'user_level' => $row->user_level);
if($remember == 1):
setcookie("login_user",session_id(),time() + (86400*7)); // 604800 = 1 week
endif;
// Free the memory and close the connection
mysqli_free_result($result);
mysqli_close($link);
// Take the user to the successive page if no errors
header("location: /");
endif;
endif;
HTML code to create the logout element:
<a href="/logout" title="Logout">
<img src="<? echo ASSETS . IMAGES . ICONS . GENERAL; ?>logout.png" alt="User Logout">
</a>
PHP code that runs when a user logs out:
function logout() {
// Load the db connect function to pass the link var
$link = db_connect();
if(is_array($_SESSION['login'])):
// Update the logged field to show user as logged out
$update = mysqli_query($link,"UPDATE web_users SET logged='0' WHERE id='".$_SESSION['login']['id']."'") or die(mysqli_error($link));
// Free the memory and close the connection
mysqli_free_result($update);
mysqli_close($link);
// Unset all of the session variables.
$_SESSION = array();
// If it's desired to kill the session, also delete the session cookie.
// Note: This will destroy the session, and not just the session data!
if(isset($_COOKIE[session_name()])):
setcookie(session_name(), '', time()-7000000, '/');
endif;
// Finally, destroy the session.
session_destroy();
// Take the user to the successive page if no errors
header("location: /");
endif;
}
The user, when logged in with the remember me checkbox to your site, will have two cookies. The session cookie, by default PHPSESSID, and the remember me cookie, login_user. In order to remove the session, you just remove the sesion cookie with this code:
if(isset($_COOKIE[session_name()])):
setcookie(session_name(), '', time()-7000000, '/');
endif;
The issue is that, aside from that, you need to unset the remember me cookie, with the following code.
if(isset($_COOKIE['login_user'])):
setcookie('login_user', '', time()-7000000, '/');
endif;
I would hazard a guess that your code
if(isset($_COOKIE[session_name()])):
setcookie(session_name(),'',time()-7000000,'/');
endif;
is your problem. Most likely the isset is returning false. I would remove it from the if statement if possible.
Also in addition as mentioned below in the comments. Did you use session_start()? There is no reference to it in your code above. This would cause session_name() to return empty.
To delete a cookie, you should set the expiration date in the past:
setcookie('login_user', '',time() - 3600);
You have this rule, but explicitly add the path parameter, although you have NOT used the path when setting the cookie, this might be the problem.

Trying to get a login to last 10 days

I'm using a login system, and I'm trying to keep the user logged in for 10 days unless they specifically log out. I thought by using session_set_cookie_params('864000'); that it would make the user stay logged in for 10 days. But it's not doing that, at least in Chrome. The user only seems to be logged in for the standard 20-30 minutes before being automatically logged out. When I check the cookies in Chrome, there are two PHP Session cookies listed for my URL with expiration dates 10 days into the future. But this seems to be unrelated to the login variables. Most of the relevant code should be below.
Any idea why the user is not logged in for 10 days?
Thanks in advance,
John
In the index file, I have the following:
require_once "header.php";
//content
include "login.php";
In the header.php file, the following is included:
session_set_cookie_params('864000');
session_start();
In the login.php file, the following is included:
if (checkLogin($_POST['username'], $_POST['password']))
{
show_userbox();
}
Here is the function "checkLogin":
function checkLogin($u, $p)
{
global $seed; // global because $seed is declared in the header.php file
if (!valid_username($u) || !valid_password($p) || !user_exists($u))
{
return false; // the name was not valid, or the password, or the username did not exist
}
//Now let us look for the user in the database.
$query = sprintf("
SELECT loginid
FROM login
WHERE
username = '%s' AND password = '%s'
AND disabled = 0 AND activated = 1
LIMIT 1;", mysql_real_escape_string($u), mysql_real_escape_string(sha1($p . $seed)));
$result = mysql_query($query);
// If the database returns a 0 as result we know the login information is incorrect.
// If the database returns a 1 as result we know the login was correct and we proceed.
// If the database returns a result > 1 there are multple users
// with the same username and password, so the login will fail.
if (mysql_num_rows($result) != 1)
{
return false;
} else
{
// Login was successfull
$row = mysql_fetch_array($result);
// Save the user ID for use later
$_SESSION['loginid'] = $row['loginid'];
// Save the username for use later
$_SESSION['username'] = $u;
// Now we show the userbox
return true;
}
return false;
}
Looks more likely that your server is discarding the sessions -- you'd need to store pertinent information in a local friendly database and load from there, based on the cookies as appropriate

Categories