You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

移动端应用PHP场景下Cookie失效问题排查求助

OAuth 2.0回调时无法读取同域Cookie/Session的问题

我的移动端应用通过OAuth 2.0向第三方网站请求授权码,回调到auth.example.com/redirect.php换取access token后,需要将token关联用户UUID存入Firebase实时数据库。由于第三方不支持state参数,我用storeUuid.php接收编码后的UUID,存入Cookie和Session,但回调时redirect.php始终无法读取Cookie,抛出{error:UUID not found in the cookie},且print_r($_COOKIE)无输出。无UUID关联时token可正常存入Firebase。

storeUuid.php代码

<?php
// storeUuid.php
session_start();
// Function to return JSON response
function jsonResponse($data) {
    header('Content-Type: application/json');
    echo json_encode($data);
}

// Function to log errors
function logError($message) {
    error_log("Error: $message");
}

session_set_cookie_params([
    'lifetime' => 3600,
    'path' => '/', 
    'domain' => 'auth.example.com', 
    'secure' => true,
    'httponly' => true,
    'samesite' => 'None' 
  ]);

// Function to store UUID in session and cookie
function storeUUID($encodedUUID) {
    $decodedUUID = base64_decode($encodedUUID);
    
    if ($decodedUUID) {
        $_SESSION['userUid'] = $decodedUUID;
        setcookie("decodedUUID", $decodedUUID, time()+3600, "/", "auth.example.com"); 
        jsonResponse(["success" => "UUID stored in session and cookie.", "decodedUUID" => htmlspecialchars($decodedUUID), "sessionId" => session_id(), "cookie" => ($_COOKIE)]);
    } else {
        logError("No UUID provided or decoding failed.");
        jsonResponse(["error" => "No UUID provided or decoding failed.", "sessionId" => session_id()]);
    }
}

// Check if the request method is POST
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $data = json_decode(file_get_contents('php://input'), true);
    $encodedUUID = isset($data['encodedUserUid']) ? $data['encodedUserUid'] : null;

    if ($encodedUUID) {
        storeUUID($encodedUUID);
    } else {
        logError("No encoded UUID provided in POST request.");
        jsonResponse(["error" => "No encoded UUID provided in POST request.", "sessionId" => session_id()]);
    }
} else {
    logError("Invalid request method.");
    jsonResponse(["error" => "Invalid request method.", "sessionId" => session_id()]);
}
?>

redirect.php代码

<?php
// redirect.php
session_start();
require __DIR__.'/vendor/autoload.php';

use Kreait\Firebase\Factory;
use Kreait\Firebase\Exception\FirebaseException;

$serviceAccountPath = __DIR__.'/1234ABCD.json';
$databaseUrl = 'https://fundraiser-application-example.com';

function jsonResponse($data) {
    header('Content-Type: application/json');
    echo json_encode($data);
}

// Function to log errors
function logError($message) {
    error_log("Error: $message");
}

// Retrieve the decoded UUID from the cookie
if (isset($_COOKIE['decodedUUID'])) {
    $decodedUUID = $_COOKIE['decodedUUID'];
} else {
    logError("UUID not found in the cookie");
    jsonResponse(["error" => "UUID not found in the cookie"]);
    exit;
}

print_r($_COOKIE); 

if (!isset($_SESSION['userUid'])) {
    logError("User UID not found in session");
    jsonResponse(["error" => "User UID not found in session"]);
    exit;
}

try {
    $firebase = (new Factory)
        ->withServiceAccount($serviceAccountPath)
        ->withDatabaseUri($databaseUrl)
        ->createDatabase();
} catch (FirebaseException $e) {
    logError("Firebase Error: " . $e->getMessage());
    jsonResponse(["error" => "Firebase Error: " . $e->getMessage()]);
    exit;
} catch (Exception $e) {
    logError("General Error: " . $e->getMessage());
    jsonResponse(["error" => "General Error: " . $e->getMessage()]);
    exit;
}

$clientID = 'MY_CLIENT_ID';
$clientSecret = 'MY_SECRET_Key';
$tokenURL = 'https://auth.3rdparty.com/oauth/token';

if (isset($_GET['code'])) {
    $authorizationCode = $_GET['code'];
    $postData = http_build_query([
        'grant_type' => 'authorization_code',
        'client_id' => $clientID,
        'client_secret' => $clientSecret,
        'code' => $authorizationCode,
        'redirect_uri' => 'https://auth.example.com/redirect'
    ]);

    $context = stream_context_create([
        'http' => [
            'method' => 'POST',
            'header' => "Content-Type: application/x-www-form-urlencoded\r\n",
            'content' => $postData
        ]
    ]);

    $response = file_get_contents($tokenURL, false, $context);

    if ($response === FALSE) {
        logError("Error in token request");
        jsonResponse(["error" => "Error in token request"]);
        exit;
    }

    $responseData = json_decode($response, true);

    if (isset($responseData['access_token'])) {
        $accessToken = $responseData['access_token'];
        $userUid = $_SESSION['userUid'];

        $firebase->getReference('users/' . $userUid . '/example/access_token/')->set($accessToken);
        jsonResponse(["success" => "Access Token stored successfully for user", "userUid" => htmlspecialchars($userUid)]);
        
        $_SESSION = array();
        session_destroy();
    } else {
        logError("Access token not found in response or user UID not available in session");
        jsonResponse(["error" => "Access token not found in response or user UID not available in session", "response" => $responseData]);
    }
} else {
    logError("Authorization code not found");
    jsonResponse(["error" => "Authorization code not found"]);
}
?>

运行日志

LOG  Initiating OAuth process...
 LOG  Encoded user UID: ABCD1234
 LOG  Response from storeUuid.php: Array
(
    [decodedUUID] => BFM6OIHuCBe56s08cgcnmiEotff1
    [PHPSESSID] => lgh2gphfbbolcimv0abkkmrere
)
{"success":"UUID stored in session and cookie.","decodedUUID":"5678DCBA","sessionId":"my_session_id","cookie":{"decodedUUID":"5678DCBA","PHPSESSID":"my_session_id"}}
 LOG  Authorization URL: https://auth.3rdparty.com/oauth/authorize?response_type=code&client_id=(MY_CLIENT_ID)&redirect_uri=https://auth.example.com/redirect&scope=read
 LOG  OAuth URL opened successfully.

解决方案建议

  • 修正Cookie参数:storeUuid.php中setcookie需补充secure和httponly参数,与Session Cookie参数保持一致,确保HTTPS环境下浏览器正常存储:

    setcookie("decodedUUID", $decodedUUID, time()+3600, "/", "auth.example.com", true, true);
    
  • 调整Session初始化顺序:session_set_cookie_params必须在session_start()之前调用,否则参数不生效。修改storeUuid.php的代码顺序:

    session_set_cookie_params([
        'lifetime' => 3600,
        'path' => '/', 
        'domain' => 'auth.example.com', 
        'secure' => true,
        'httponly' => true,
        'samesite' => 'None' 
    ]);
    session_start();
    
  • 验证跨站Cookie策略:使用SameSite=None时必须搭配secure=true,且站点必须为HTTPS环境,否则浏览器会拒绝存储Cookie。

  • 检查Session传递有效性:在redirect.php开头添加Session Cookie检查,确认Session是否正常传递:

    if (!isset($_COOKIE['PHPSESSID'])) {
        logError("Session cookie not found");
        jsonResponse(["error" => "Session cookie not found"]);
        exit;
    }
    
  • 确保域名一致性:确认storeUuid.php和redirect.php的域名完全一致,避免子域名、大小写差异导致Cookie无法读取。

内容的提问来源于stack exchange,提问作者Yanhamu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 21:30:53