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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 18:15:40