This is NOT a duplicate of this Q&A because I have checked each answer to that Q&A but none of them are improving the situation here.
Yes, the issue is a "classic" one but I can't see how to diagnose this: The session is saved to the file and the session file saves all the relevant data, but on every page load the PHP system doesn't find the existing session file and instead generates a new session.
I can't for the life of me see why this is occuring.
UPDATE:
I have found this morning (1st August) that a recent update to Firefox to 115 seems to have this side effect whereby Firefox browser can't save/load/use/reach the cookie that contains the session id or otherwise the session id is not being saved to the cookie. Please see "Update" details at the bottom of this question.
Opera, Chrome and Edge browsers work fine and carry sessions correctly.
Server
- The server runs on Plesk Obsidian 18.0.54 and is currently running PHP 7.4.33
- The server currently runs PHP as an "FPM application served by Apache" (see note at very bottom).
- The server previously ran everything in the "original" state absolutely fine and without issue.
- Session are saved using the file system.
- There is no issue with disk space usage.
Something has changed and now PHP Session id's are not being transferred between pages. Each page initiates a new session.
Local PHP.ini
The local PHP ini file has the following settings:
session.save_path="/path/to/domain.uk/sessionFolder"
session.name="randomString89"
session.use_only_cookies=1
session.cookie_httponly=1
session.cookie_secure=1
session.cookie_samesite="Strict"
session.cookie_domain=".domain.uk"
session.cookie_path=/
session.sid_length=128
I have tweaked some of these settings (exploring cookie_samesite="Lax"
) and also removing quotes around strings and these have made no difference to the issue.
Original Structure
The first page in question (A.php
) has a few included files:
A.php
-- Header.php
-- Preloader.php
-- Core page script
header.php
A standard header that is universal to all pages on the website and which sets header info such as HTTP headers as well as ensuring the autoloader is correctly set and that a PHP session is active.
error_reporting(E_ALL &~E_NOTICE);
if (session_status() === PHP_SESSION_NONE){
session_set_cookie_params( 4000, '/', '.domain.uk' , true, true );
session_start();
}
header("Cache-Control: no-cache, must-revalidate"); //HTTP 1.1
header('Content-Type: text/html; charset=utf-8');
header("Content-Language: en");
header("Content-Security-Policy: upgrade-insecure-requests;");
header("Referrer-Policy: origin-when-cross-origin"); //referrer for Chrome
header("Referrer-Policy: strict-origin-when-cross-origin");
...
use \namespace\reference\donehere;
// custom autoloader (100% works)
require str_ireplace("/public_html","/classes",$_SERVER['DOCUMENT_ROOT'])."/autoloader.php";
I have explored all sorts of variations with this such as setting the session cookie lifetime to 0
, confirming the domain is fine, even disabling the session_set_cookie_params()
line entirely. No changes to the behaviour.
preloader.php
After the header, the first page loads a "preload" include script which sets a few session variables for use for the entire client visit. This works perfectly and only interacts with sessions here:
if( empty($_SESSION['reference']) || (time() - (int)$_SESSION['referenceTime']) > 15 ) {
$_SESSION['reference'] = "generated value here";
$_SESSION['referenceTime'] = time();
error_log("\nNEW checkDrop set in ".__FILE__." as: ".print_r($_SESSION,true));
}
elseif(strlen($_SESSION['reference'])> 0) {
error_log("\ncheckDrop already exists: ".print_r($_SESSION,true));
}
These are brought together within the first page, A.php
:
A.php
<?php
use \namespace\reference\donehere;
require $_SERVER['DOCUMENT_ROOT']."/path/to/header.php";
include $_SERVER['DOCUMENT_ROOT']."/path/to/preloader.php";
if (isset($_GET['msg'])) {
$_SESSION['message'] = trim(($_SESSION['message']??'').' '.urldecode($_GET['msg']));
}
?>
<!DOCTYPE html>
<html class="no-js" lang="en-GB">
<head>
<meta charset="utf-8">
<title>title</title>
<link rel="canonical" href="https://www.domain.uk/A.php" >
<?php
include $_SERVER['DOCUMENT_ROOT']."/path/to/html_only_metaheader.php";
?>
</head>
<body>
<main>
<section>
<form name="form1" method="post" action="/B.php"
enctype="multipart/form-data" accept-charset="UTF-8">
there then follows a form which contains a hidden field holding some session data:
<input type='hidden' name='xxxx' value='<?php
// value comes from the preloader include above.
print $_SESSION['reference']??'';
?>'>
At the bottom of the page is session debug output which always shows the correct data and the same as the HTML form above:
</body>
</html>
<?php
error_log("base of start: ".print_r($_SESSION,true));
error_log("Session ID: ". print_r(session_id()??'none',true));
B.php
- header.php
- Session and POST data processing in the script.
And that's it, the original page was not in the same folder but even in the same folder there is a complete failure for the session to realise there's an existing session associated with this
<?php
use \namespace\reference\donehere;
require $_SERVER['DOCUMENT_ROOT']."/path/to/header.php";
error_log("Session ID 3: ". print_r(session_id()??'none',true));
error_log("name of session 3: ".print_r(session_name(),true));
Things I've done to explore this issue:
- Session name ("randomString89") is universal throughout all pages/include.
- (Prolific) error log reporting shows SESSION data is being written to file.
- Have tried disabling/skipping
session_set_cookie_params
(it's all set in the ini anyway tbh) - Trying to set samesite.cookie to
Lax
- And ensuring domain is open
/
or open to www. or other variations.domain.uk
- Session status is confirmed as
"active" (2)
on all pages after the header.phpsession_start();
- There is no whitespace (that I can see) that would interfer with session triggering.
PHPinfo
shows nothing unexpected and everything appears correct under the "local" column.- All found StackOverGnome solutions don't resovlve this or don't apply (outlined at the top of this question)
- I have spent many hours today methodically working through possibilities here and not found anything. What have I missed?
How can I diagnose this problem?
- Server note: The server currently runs PHP as an "FPM application served by Apache". There are options here to change this to "FPM application served by nginx" or "fastCGI", I have never changed this on this server and not sure what this could entail?
Updates
I have found some unexpected updates: The issue appears to be specific to Firefox 115. I have tried Opera Browser (v100), and Chrome (v115) and even MS Edge (v109) and they all work fine, but Firefox persists in not recognising the session id . Strangely, in other websites (both mine and 3rd party) there is not log in issues with Firefox so kind of curious why this seems browser specific.
To answer queries from the comments:
- The page saves the session data fine, and checking the raw session file in the filesystem confirms this.
- Every page loads "header.php".
- I have tried both using
.domain.uk
andwww.domain.uk
anddomain.uk
and these don't make a difference. - Disabling Firefox's "Enhanced Tracking Protection" does not resolve this issue.
To underline, the issue doesn't appear to be the session mechanism itself, but somehow the browser (Firefox 115) doesn't seem to be saving the [correct?] session ID to the cookie or similar inconsistency.