Fix session cookie not persisting due to Partitioned attribute

The TOKEN cookie set by UniFi OS includes the 'Partitioned' attribute
(CHIPS), which some libcurl versions do not write to the Netscape cookie
jar file. This caused every API request to go out unauthenticated,
resulting in 401/403 errors even after a successful login.

Fix: extract the TOKEN value directly from the Set-Cookie response
header in login() and pass it via CURLOPT_COOKIE in apiRequest(),
bypassing the broken file-based cookie jar. Cookie file remains as
fallback for environments where extraction fails.

Also update test.php section 8 to validate this fix and show the
extracted cookie value.

https://claude.ai/code/session_01UsuvFAmmeagtQa14QA4iaq
This commit is contained in:
Claude 2026-04-22 05:41:42 +00:00
parent e705458af3
commit 897392041a
No known key found for this signature in database
2 changed files with 47 additions and 8 deletions

View file

@ -190,29 +190,52 @@ try {
if (file_exists($cookieFile)) {
$cookieContents = file_get_contents($cookieFile);
echo "<strong>Cookie-Datei:</strong><pre style='background:#f4f4f4;padding:8px;font-size:12px'>";
echo htmlspecialchars($cookieContents ?: '(leer)');
echo htmlspecialchars($cookieContents ?: '(leer — TOKEN hat Partitioned-Attribut, libcurl schreibt es nicht in die Jar-Datei)');
echo "</pre>";
}
// Extract TOKEN from Set-Cookie header (the fix for Partitioned cookie issue)
$tokenCookie = null;
foreach ($responseHeaders as $h) {
if (stripos($h, 'set-cookie:') === 0) {
$cookieVal = trim(substr($h, strlen('set-cookie:')));
$cookieParts = explode(';', $cookieVal);
$first = trim($cookieParts[0]);
if (strpos($first, 'TOKEN=') === 0) {
$tokenCookie = $first;
}
}
}
if ($tokenCookie) {
echo "✓ TOKEN aus Set-Cookie-Header extrahiert: <code>" . htmlspecialchars(substr($tokenCookie, 0, 40)) . "…</code><br>";
} else {
echo "✗ TOKEN nicht in Set-Cookie-Header gefunden<br>";
}
// --- API Test (only if login succeeded) ---
if ($httpCode === 200) {
echo "<strong>API-Test (stat/voucher GET):</strong><br>";
echo "<br><strong>API-Test (stat/voucher GET) — mit extrahiertem Cookie:</strong><br>";
$apiHeaders = ['Content-Type: application/json'];
if ($csrfToken !== null) {
$apiHeaders[] = 'X-CSRF-Token: ' . $csrfToken;
}
$ch2 = curl_init();
curl_setopt_array($ch2, [
$apiOpts = [
CURLOPT_URL => $controllerUrl . "/proxy/network/api/s/" . $site['site_id'] . "/stat/voucher",
CURLOPT_HTTPGET => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_COOKIEFILE => $cookieFile,
CURLOPT_TIMEOUT => 10,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_HTTPHEADER => $apiHeaders,
]);
];
if ($tokenCookie !== null) {
$apiOpts[CURLOPT_COOKIE] = $tokenCookie;
} else {
$apiOpts[CURLOPT_COOKIEFILE] = $cookieFile;
}
curl_setopt_array($ch2, $apiOpts);
$apiBody = curl_exec($ch2);
$apiCode = curl_getinfo($ch2, CURLINFO_HTTP_CODE);
$apiErr = curl_error($ch2);