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

如何通过PHP8 Google客户端+Javascript授权码获取用户数据

Google登录跨端(Vue+PHP)授权错误解决:invalid_grant

问题背景

我有一个正常运行的Vue应用,已经通过Google JavaScript SDK实现用户登录,拿到了一个类似token/code的凭证(不确定具体名称)。现在要把这个凭证传给用Google API PHP Client开发的PHP后端,但不知道后续怎么处理。查文档没找到明确要用到的类和方法,试了下面的代码:

$this->google_client = new Client();
$this->google_client->setClientId(config('services.google')['client_id']);
$this->google_client->setClientSecret(config('services.google')['client_secret']);

//$this->google_client->setAccessToken($token);
$this->google_client->addScope('openid');
$this->google_client->addScope('email');
//$this->google_client->addScope('profile');
$access_token = $this->google_client->fetchAccessTokenWithAuthCode($token);

Log::info($access_token);

$this->google_client->setAccessToken($access_token);

但日志里报了这个错误:

[
  'error' => 'invalid_grant',
  'error_description' => 'Bad Request',
]  

问题根源&解决步骤

1. 明确前端传递的凭证类型

Google JS SDK登录后,你拿到的不是access_token,而是授权码(authorization code)——只有这个码能传给后端去兑换真正的access_token。如果前端误传了id_token或者前端自己的access_token给后端,必然触发invalid_grant错误。

前端正确获取授权码的示例(Vue环境):

// 初始化授权码客户端
const codeClient = google.accounts.oauth2.initCodeClient({
  client_id: '你的Google客户端ID',
  scope: 'openid email profile',
  ux_mode: 'popup',
  callback: (response) => {
    // 这里的response.code就是要传给后端的授权码
    axios.post('/api/google-login', { code: response.code });
  }
});

// 触发登录弹窗
codeClient.requestCode();

2. 修正后端代码逻辑

你的代码框架没问题,但缺少关键配置和校验,修正如下:

$this->google_client = new Client();
$this->google_client->setClientId(config('services.google')['client_id']);
$this->google_client->setClientSecret(config('services.google')['client_secret']);
// 核心配置:针对前端无跳转登录场景,redirect_uri必须设为'postmessage'
$this->google_client->setRedirectUri('postmessage');
// 一次性添加所有需要的权限
$this->google_client->addScope(['openid', 'email', 'profile']);

// 确保$token是前端传来的授权码(authorization code)
$access_token = $this->google_client->fetchAccessTokenWithAuthCode($token);

// 先检查是否返回错误
if (isset($access_token['error'])) {
    return response()->json(['msg' => $access_token['error_description']], 400);
}

// 设置access_token,后续可调用Google API获取用户信息
$this->google_client->setAccessToken($access_token);

// 示例:获取用户基本信息
$oauth_service = new \Google\Service\Oauth2($this->google_client);
$user_profile = $oauth_service->userinfo->get();

// 输出用户信息(可根据业务逻辑存储或处理)
Log::info('Google用户信息:', [
    'email' => $user_profile->getEmail(),
    'name' => $user_profile->getName(),
    'avatar' => $user_profile->getPicture()
]);

3. 其他排查要点

  • 授权码只能用一次:如果前端重复提交同一个授权码,会直接触发invalid_grant,确保每次登录都获取新的授权码。
  • Google控制台配置校验:确认客户端ID、密钥与代码中一致,且已在控制台启用OAuth2.0 API(无需额外付费,默认可启用)。
  • 服务器时间同步:若服务器本地时间与Google服务器时间偏差超过5分钟,会导致授权码验证失败,检查服务器时区和时间是否正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 14:53:11