使用Socialite实现Authorization Code Grant时$response返回null排查
调用Passport的/oauth/token接口返回null的排查与解决
核心逻辑错误
Socialite回调里拿到的code是谷歌OAuth的授权码,这个码已经被Socialite::driver('google')->user()用来换取谷歌用户信息了,属于一次性消耗的凭证,不能再传给Passport的/oauth/token接口当授权码用,这是你当前问题的根本原因。
其他可能导致返回null的原因
- 请求未成功完成:先检查请求的状态码和响应体,比如先打印
$response->status()和$response->body(),如果后端返回500错误、网络不通或者请求被拦截,$response->json()就会返回null。 - 客户端类型不匹配:你创建的是Personal Passport客户端,但授权码模式(
authorization_code)需要的是**密码授权客户端(Password Grant Client)**或者标准的授权码客户端,Personal Client不支持授权码流程。 - 参数不一致:
redirect_uri必须和创建客户端时填写的完全一致,包括域名、路径、http/https协议,差一个斜杠都不行。- 不需要对
code做urldecode,request()->query('code')已经自动处理了解码,手动解码会导致参数失效。
- 冗余操作干扰:你调用
$user->createToken('PKCE')->accessToken是生成个人访问令牌,和授权码流程完全无关,属于多余操作,没必要保留。
修正后的实现思路
如果你的需求是通过谷歌登录后给前端返回Passport令牌,正确的做法是用密码模式生成令牌(因为已经通过谷歌验证了用户身份),示例代码如下:
public function callbackGoogle() { $googleUser = Socialite::driver('google')->stateless()->user(); // 查找或创建用户 $user = User::firstOrCreate( ['email' => $googleUser->email], ['name' => $googleUser->name] ); // 获取密码授权客户端 $client = DB::table('oauth_clients')->where('password_client', true)->first(); // 调用密码模式接口生成令牌 $response = Http::asForm()->post('http://localhost:5000/oauth/token', [ 'grant_type' => 'password', 'client_id' => $client->id, 'client_secret' => $client->secret, 'username' => $user->email, 'password' => $user->password ?? Str::random(16), // 若用户无密码则生成随机密码 'scope' => '', ]); dd($response->json()); }
如果一定要用授权码模式,应该让前端先发起Passport的授权流程,在Passport的授权页面中集成谷歌登录选项,而不是先通过Socialite登录再调用/oauth/token接口。
内容的提问来源于stack exchange,提问作者henrbu
相关产品推荐
相关产品推荐

