如何通过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
相关产品推荐
相关产品推荐

