Laravel 9中Google Access Token刷新失败:refresh token缺失求助
解决Google Forms令牌无法刷新的问题
问题根源
你遇到的refresh token must be passed in or set as part of setAccessToken错误,核心原因是首次获取令牌时没有完整保存包含refresh_token的令牌数组,导致刷新时无法读取到有效的refresh_token;同时刷新代码存在逻辑错误,进一步加剧了问题。
修复步骤
1. 修正令牌获取代码
首先优化首次授权获取令牌的代码,确保保存完整的令牌数据(包含refresh_token):
$client = new \Google_Client(); // 移除废弃的setAuthConfigFile方法,仅保留setAuthConfig $client->setAuthConfig(base_path().'/google-config.json'); $client->setRedirectUri('https://example.com/get-token'); $client->addScope("https://www.googleapis.com/auth/forms.body"); $client->addScope("https://www.googleapis.com/auth/forms.responses.readonly"); $client->setAccessType('offline'); // 必须设置为offline才能获取refresh_token $client->setApprovalPrompt('force'); if (! isset($_GET['code'])) { $auth_url = $client->createAuthUrl(); return redirect(filter_var($auth_url, FILTER_SANITIZE_URL)); } else { $client->authenticate($_GET['code']); // 获取完整的令牌数组(包含access_token、refresh_token等字段) $fullToken = $client->getAccessToken(); // 将完整令牌写入文件,确保refresh_token被保存 file_put_contents(storage_path('google_tokens.json'), json_encode($fullToken)); }
2. 修正令牌刷新代码
重新编写刷新逻辑,确保正确读取refresh_token并更新令牌:
$client = new \Google_Client(); $client->setAuthConfig(base_path().'/google-config.json'); $client->addScope("https://www.googleapis.com/auth/forms.body"); $client->addScope("https://www.googleapis.com/auth/forms.responses.readonly"); // 加载保存的完整令牌数据 $tokenPath = storage_path('google_tokens.json'); if (file_exists($tokenPath)) { $accessToken = json_decode(file_get_contents($tokenPath), true); $client->setAccessToken($accessToken); } // 检查令牌是否过期 if ($client->isAccessTokenExpired()) { // 获取保存的refresh_token $refreshToken = $client->getRefreshToken(); // 如果refresh_token为空,说明之前未正确保存,需要重新引导用户授权 if (!$refreshToken) { return redirect()->to('/get-token'); } // 使用refresh_token获取新的access_token $newAccessToken = $client->fetchAccessTokenWithRefreshToken($refreshToken); // 合并原有refresh_token到新令牌数组(新响应不包含refresh_token) $newAccessToken['refresh_token'] = $refreshToken; // 更新客户端令牌 $client->setAccessToken($newAccessToken); // 保存更新后的完整令牌 file_put_contents($tokenPath, json_encode($newAccessToken)); }
关键注意事项
refresh_token仅首次授权返回:只有用户首次同意offline访问权限时,Google才会返回refresh_token,后续刷新令牌不会再返回该字段,因此必须在首次获取时完整保存。- 废弃方法移除:
setAuthConfigFile是Google Client库的旧方法,已被setAuthConfig替代,无需重复调用。 - 刷新后令牌合并:新获取的access_token不包含refresh_token,必须将原有refresh_token合并后再保存,否则下次刷新会再次失败。
内容的提问来源于stack exchange,提问作者adeveloper
相关产品推荐
相关产品推荐

