socialiteproviders/laravelpassport的getAccessTokenResponse返回空响应求助
问题场景
我们基于socialiteproviders/laravelpassport实现OAuth2.0用户认证:
- 授权跳转流程正常:调用
Socialite::driver('laravelpassport')->scopes(['offline_access'])->redirect()->getTargetUrl()能正确获取code和state值 - 但用
code兑换用户信息时失败:执行Socialite::driver('laravelpassport')->stateless()->setHttpClient(new \GuzzleHttp\Client(['verify' => false]))->user()无法拿到用户详情,排查发现getAccessTokenResponse($code)返回空对象{} - CAS服务器日志显示已成功生成
access_token,但上述函数接收的响应为空
相关核心代码:
public function getAccessTokenResponse($code) { $response = $this->getHttpClient()->post($this->getTokenUrl(), [ RequestOptions::HEADERS => $this->getTokenHeaders($code), RequestOptions::FORM_PARAMS => $this->getTokenFields($code), ]); return json_decode($response->getBody(), true); }
其中:
getTokenHeaders返回:return ['Accept' => 'application/json'];getTokenFields返回:
[ 'grant_type' => 'authorization_code', 'client_id' => $this->clientId, 'client_secret' => $this->clientSecret, 'code' => $code, 'redirect_uri' => $this->redirectUrl, ]
CAS服务器日志片段:
Created access token TST-accesstokengenerated, now encoding it as base64 2025-04-09 INFO OAuth access token response: access_token=encodedTST-accesstokengenerated&expires_in=6199
排查与解决方案
1. 响应格式不匹配(核心原因)
从CAS日志可见,服务器返回的是key=value的表单格式,但代码中请求头指定了Accept: application/json,若CAS不支持根据Accept头切换响应格式,依然返回表单数据,会导致json_decode解析空字符串得到空对象。
修复方法:修改getAccessTokenResponse方法,兼容表单格式解析:
public function getAccessTokenResponse($code) { $response = $this->getHttpClient()->post($this->getTokenUrl(), [ RequestOptions::HEADERS => $this->getTokenHeaders($code), RequestOptions::FORM_PARAMS => $this->getTokenFields($code), ]); $body = $response->getBody()->getContents(); // 判断是否为表单格式,是则解析为数组 if (str_contains($body, '=')) { parse_str($body, $result); return $result; } return json_decode($body, true) ?: []; }
2. 补充Guzzle配置,处理重定向与编码
部分CAS服务器会在返回token时触发重定向,默认Guzzle未开启自动重定向;或响应编码问题导致解析失败,可补充配置:
$client = new \GuzzleHttp\Client([ 'verify' => false, 'allow_redirects' => true, // 开启自动重定向 'decode_content' => true, // 自动解码响应内容 ]); Socialite::driver('laravelpassport')->stateless()->setHttpClient($client)->user();
3. 严格校验redirect_uri参数
确认redirect_uri与授权跳转时的地址完全一致(包括域名、路径、末尾斜杠等),CAS对该参数的校验通常是严格匹配的,参数不匹配会导致静默返回空响应。
4. 开启Guzzle调试日志抓包
添加日志配置查看完整请求/响应细节,定位问题:
$client = new \GuzzleHttp\Client([ 'verify' => false, 'debug' => fopen(storage_path('logs/guzzle_oauth.log'), 'a'), // 写入调试日志 ]);
执行请求后查看storage/logs/guzzle_oauth.log,可确认实际收到的响应内容。
内容的提问来源于stack exchange,提问作者SDLBeginner
相关产品推荐
相关产品推荐

