PHP setcookie has stopped working with no code change - php

I know this question gets asked a million times but this one is very different. This code has worked flawlessly for over 3 years but now has stopped working.
The cookie in question holds a members id for an 'auto login' when returning to the site. The cookie is set via a jQuery call to a function upon log in. Once they are logged in the function returns a value and the calling script redirects the member to their control panel:
if (strlen(trim($_POST['keep_logged'])) != 0) {
if(setcookie('foacmemberinformation', $row['member_id'], time() + 60 * 60 * 24 * 365, '/')) {
error_log('in set cookie line 68');
}
else {
error_log('set cookie failed');
}
}
I just added the if else statement around the set cookie to verify that the set cookie function is returning true.
What seems to be causing it is when a member uses the 'log out' function on the site which is as simple as this:
session_start();
session_destroy();
setcookie('foacmemberinformation', '', time() - 3600);
header('Location: /Member-Login');
Now I personally have used this log out, then log back in and remember function hundreds if not thousands of times over the past three year and have never had an issue until now. It also is happening in all browsers.
I have verified that setcookie is returning true and there is no output before except another cookie (setcookie('foacmemberstate', $row['state'], time() + 60 * 60 * 24 * 14, '/');) which IS being set. I even commented that set cookie out and tried and still the 'problem' cookie is not setting.
I don't get what is happening after it worked for 3 years!

Related

PHP : Users getting logged out

I have a custom written PHP application. Build 15 years ago. Working perfectly fine until recently when users reported they are being logged out even while they are actively using the application.
We use PHP sessions to manage users. The session expiry is set to 12 hours of inactivity. I reproduced the issue of being logged out. There is no pattern. at times I was logged out after 30 mins, at times 2 hours, at times 40 mins and so on. I captured the PHP session cookie and checked that the corresponding PHP session file existed in the tmp directory on the server. The session file was there on the server even when the application got me logged out and it was not even 2 hours (expiry set for 12 hours).
If I print the $_SESSION, this issue does not appear as much. Reproduced the issue in Chrome and Firefox. I have session_start and session_destroy only in logout service.
Any leads what could be causing this?
I faced same problem a few times. Workaround: use a "remember me" cookie for auto login.
Here's a recipe:
Whenever user logins successfully run this:
// remember me for a year every login
$login_string = hash('sha512', $user_id . $_SERVER['HTTP_USER_AGENT'] . time());
Project::update_table_record('users', $user_id, ["remember_me" => $login_string]);
$cookie_name = COOKIE_REMEMBER_ME;
$cookie_value = $login_string;
setcookie($cookie_name, $cookie_value, time() + (86400 * 365), "/"); // 365 day example
Whenever user chooses to logout, give him the option:
setcookie(COOKIE_REMEMBER_ME, "", time() - 3600, "/");
Otherwise, if no session then re-login if cookie is valid.
// auto login / remember me!
if (!LiveUser::get_id()) {
if (isset($_COOKIE[COOKIE_REMEMBER_ME])) {
$user_string = $_COOKIE[COOKIE_REMEMBER_ME];
$user_id = Project::get_value('users', ['remember_me' => $user_string], 'id');
if ($user_id) {
Project::do_login($user_id);
}
}
}

PHP session logs out before session cookie expires

I have set up cookie lifetime to last a complete day, but after 15-20 mins of idle time, I get logged out anyways. The strangest thing is that everything runs fine on localhost, but when I took my website live, I started experiencing this problem with the same exact code.
I read on stackoverflow that it could be related to session.gc_maxlifetime, so I have even edited that on the .htaccess level. I have changed it from 1440 to 86400, but the problem still persists.
Here is the rundown of my code.
When a user logs in, I check if the user already has a cookie named 'AUTHID'. If the user does, I first delete it.
if (isset($_COOKIE['AUTHID'])) {
unset($_COOKIE['AUTHID']);
setcookie('AUTHID', null, -1, '/');
}
After that, depending on if the user selected Remember Me option, I set the cookie lifetime value, and it creates a cookie that I can see in Chrome Settings with absolutely correct expiration time.
session_name('AUTHID');
ini_set('session.cookie_httponly', 1);
if(isset($_POST['remember-me'])) {
ini_set('session.gc_maxlifetime', 604800);
session_set_cookie_params(604800,"/");
} else {
ini_set('session.gc_maxlifetime', 86400);
session_set_cookie_params(86400,"/");
}
session_start();
Lastly, I have a php function to check if the user is logged in on every single page:
$rel_url = "$_SERVER[REQUEST_URI]";
session_name('AUTHID');
session_start();
if(!isset($_SESSION['user_id'])) {
if (strpos($rel_url, 'login=success') !== false) {
header('Location: index.php');
}
header('Location: login-with-bg.php?access-denied=logged-out');
exit();
}
This works perfectly fine on my localhost, but when I uploaded this code on my hosting server, even though the cookie is still being created with correct expiration date, but if my browser is idle for 15-20 mins, my session gets timed out.
EDIT: from an article, I got an idea of making AJAX calls every 10 mins or so, and that works when the browser is open. However, I need a complete method that works even if the browser is closed.
EDIT2: The AJAX code that I have for keeping the session alive:
function keep_alive() {
$.get('index.php',null)
}
keep_alive_interval = setInterval(keep_alive, 600000)
A few notes:
Session and ajax is a tricky thing. Be sure to close your session when doing an ajax call so it writes changes to your session. (register_shutdown_function("session_write_close");)
In this case there is no real use in changing the sessionname (default will do).
The AUTHID cookie stores your session_id which corresponds to your session. This has to be set also. No need to manually set the cookie
This is working for me on the server but not on local machines
if ($_SERVER['SERVER_ADDR'] != '127.0.0.1'){ // Only use custom session on server. use default settings on local machine
register_shutdown_function("session_write_close"); // write your changes done with ajax before your session opens again
// some security settings
ini_set("session.use_strict_mode", 1);
ini_set("session.cookie_httponly", 1);
ini_set("session.cookie_secure", 1);
ini_set("session.use_only_cookies", 1);
ini_set("session.gc_maxlifetime",60 * 60 * 24 * 14); // 2 weeks
session_set_cookie_params(60 * 60 * 24 * 14,"/",".yourdomain.com"); // 2 weeks
session_name("AUTHID");
if(isset($_COOKIE['AUTHID'])){
session_id($_COOKIE['AUTHID']);
}
}
session_start();

Why do my cookies expire instantly?

I have a function that sets cookies; in this function I use PHP's setcookie function in order to set cookies, for example:
setcookie('auth', $token, time() + 3600);
The function I'm using setcookie in is as follows:
function SetAuthenticationCookie($id, $rememberme) {
$token = md5(uniqid(mt_rand(), true));
executeNonUserQuery([db query]);
if ($rememberme) {
setcookie('auth', $token, time() + (86400 * 90));
setcookie('profid', $id, time() + (86400 * 90));
}
else
{
setcookie('auth', $token, time() + 3600);
setcookie('profid', $id, time() + 3600);
}
}
The above cookie should be valid for one hour, and appears this way in the browser (see below screenshot).
In the browser the cookies show before it redirects (the page is dynamic), therefore the cookies are being set. However they disappear when the page redirects. This causes a problem because the main UI page (where the login page redirects) checks for the presence of the authentication cookies and redirects back to the login page if they don't exist.
I followed the official documentation for setcookie and am unable to see what the problem is. Chrome reports that the cookie path is /internal therefore it's a possibility that the actual page can't access them (the page path is /pages), but this still doesn't explain why they disappear completely from Chrome.
The cookie is set to expire in an hour after it is set, but this doesn't explain the disappearance of the cookies unless I'm missing something crucial in setcookie concerning the setting of the expiration time. I experience the same issue in other browsers, so it has to be something that I've done wrong or missed.
I confirm that I have nothing that unsets or expires the cookies (I haven't implemented that yet). I've tried setting the path to / but this doesn't fix the problem.
What am I doing wrong, and how can I fix it?
I'm aware of the security issues here, my priority is to fix this problem first.
This issue was caused by two factors:
The cookie path
PHP's timezone
As mentioned in the question I had already tried setting the cookie path to / with no effect. However I did not consider PHP's timezone, which was set to UTC.
Setting the timezone to the correct Europe/Guernsey plus setting the cookie path to / (root) fixed the issue.
Ok, add a path and make it available to the whole website rather than just the folder the first script is in
setcookie('auth', $token, time() + 3600, '/');

Can't update cookie

I'm running into a strange problem, I can't update cookies. I'm perfectly able to read it and to set it (just the first time). Then every time I try to update it (for logout or update the cookie's info) nothing happens.
Basically when I login I use this code
$cookie_time = (3600 * 24 * 30); // 30 days
$cookietime = time() + $cookie_time;
$cookie_name = 'login';
$cookie_value = 'enter';
setcookie ($cookie_name, 'id='.$selector.'&token='.$token, $cookietime);
and I can set it perfectly.
When I logout I use this code
$cookie_time = 1; // 1 days
$cookie_name = 'login';
$cookie_value = 'exit';
setcookie($cookie_name, $cookie_value, $cookie_time);
The cookie doesn't change at all. Even if I try to login again without logging out (I made this possible by code) the cookie doesn't change. Looks like it's impossible to update it... I made many attempts but I have no ideas how to solve it! Is it possible that my PHP doesn't allow to set cookies that are already set?
Be careful, $cookie_time should correspond to a timestamp relative to the 1 Jan 1970 and not only a time in ms.
see http://php.net/manual/fr/function.setcookie.php
$cookie_time should be :
$cookie_time = time() + (3600 * 24 * 30);
the time() function returns the actual timestamp and $cookie_time now represents a expire date in the future ;)
From the setcookie docs.
Like other headers, cookies must be sent before any output from your
script (this is a protocol restriction). This requires that you place
calls to this function prior to any output, including and
tags as well as any whitespace.
Are you outputting anything before trying to update the cookie

Unable to read cookie in php on localhost

PHP not reading cookie although I can see in browser.
//i set cookie in localhost/site/classes/php/user
setcookie("liu", $result[0]['user_id'], time() + 60 * 60 * 24 * 30, "/");
//trying to access it in localhost/site/index.php
$loggedInUser = $_COOKIE['liu'];
If you're running on localhost, you should explicitly set the cookie domain to false.
You could try:
setcookie("liu", $result[0]['user_id'], time() + 60 * 60 * 24 * 30, "/", false);
Have a further look here: Cookies on localhost with explicit domain
You cannot read a cookie you have set in the code above.
Cookies are sent with the headers to the browser.
PHP will be able to read the cookie only after the user navigates to the next page or you redirect him to a new page.
PHP will be able to read the cookie then because the browser will send it back via headers.
Read this: http://uk1.php.net/manual/en/function.setcookie.php
Common Pitfalls:
Cookies will not become visible until the next loading of a page that the cookie should be visible for. To test if a cookie was successfully set, check for the cookie on a next loading page before the cookie expires.
Expire time is set via the expire parameter. A nice way to debug the existence of cookies is by simply calling print_r($_COOKIE);
We verify that we are not working in local, if we are in local we put the value of false in the variable $domain. If not, we pass the domain where the web is hosted.
$domain = ($_SERVER['HTTP_HOST'] != 'localhost') ? $_SERVER['HTTP_HOST'] : false;
setcookie( 'liu', $result[0]['user_id'], time() + 60 * 60 * 24 * 30, '/', $domain );

Categories