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

使用Google API PHP Client复用用户登录时获取的JWT凭证调用MyBusinessAccountManagement API遇未授权错误的问题

Google API PHP Client复用用户登录时获取的JWT凭证调用MyBusinessAccountManagement API遇未授权错误的问题

我来帮你拆解这个问题的根源,以及给出可落地的解决办法:

问题出在哪?

你现在存在数据库里的google_token是ID Token(JWT格式),它的核心作用只是验证用户身份——简单说就是证明“这个用户确实是他自己”,但它完全没有被授权用来调用像MyBusinessAccountManagement这类需要特定权限的Google API。

而你在OAuth Playground拿到的是Access Token,这才是Google API认可的“访问通行证”,只有它能带着授权信息去调用受保护的API接口。这两种Token的用途、结构完全不同,直接把ID Token当Access Token用,肯定会触发unauthorized_client错误。

为什么会报这个错?

  1. ID Token的受众(aud字段)是你的客户端ID,Google API的服务端只接受带有正确权限范围(scope)和授权信息的Access Token;
  2. 你保存的ID Token根本不包含business.manage这个权限的授权记录,所以哪怕你硬把它塞给客户端当Access Token,Google的API服务器也会直接拒绝。

正确的解决流程

你需要在用户首次登录时,不仅完成身份验证,还要获取到能访问MyBusiness API的Access Token和Refresh Token(用于离线刷新过期的Access Token),具体调整步骤如下:

1. 调整登录流程,获取授权凭证

你需要切换到标准的OAuth2授权码流程(因为One Tap默认只返回ID Token,无法直接获取带权限的Access Token),让用户主动授权你的应用访问其MyBusiness数据:

前端/登录入口调整

替换原来的One Tap代码,改为引导用户走OAuth2授权流程:

<!-- 生成授权链接,client_id和redirect_uri替换为你自己的配置 -->
<a href="https://accounts.google.com/o/oauth2/v2/auth?client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&response_type=code&scope=openid%20https://www.googleapis.com/auth/business.manage&access_type=offline&prompt=consent">
  登录并授权访问我的商家账户
</a>
后端回调/登录脚本调整

当用户授权后,Google会跳转到你配置的redirect_uri,并携带授权码code,后端用这个code交换Access Token和Refresh Token:

// 回调脚本,获取授权码
$code = $_GET['code'];

$client = new \Google_Client();
$client->setAuthConfig(realpath('google.json'));
// 必须和你在Google Console配置的redirect_uri完全一致
$client->setRedirectUri('YOUR_REDIRECT_URI');
// 请求必要的权限范围
$client->addScope('openid');
$client->addScope('https://www.googleapis.com/auth/business.manage');
// 启用离线访问,确保能拿到Refresh Token
$client->setAccessType('offline');
// 强制用户确认授权,确保首次授权时能拿到Refresh Token
$client->setPrompt('consent');

// 用授权码交换Token凭证
$tokenData = $client->fetchAccessTokenWithAuthCode($code);

// 验证ID Token,获取用户唯一标识
$payload = $client->verifyIdToken($tokenData['id_token']);
if ($payload) {
    $userId = $payload['sub'];
    // 从数据库获取用户
    $user = getUser($userId);
    // 保存关键凭证到数据库
    $user->google_id = $userId;
    $user->google_refresh_token = $tokenData['refresh_token']; // 核心:离线刷新用
    $user->google_access_token = $tokenData['access_token']; // 临时访问凭证,会过期
    $user->google_token_expires = time() + $tokenData['expires_in']; // 过期时间戳
    // 保存用户数据
    saveUser($user);
}

2. 后续调用API时,用Refresh Token获取有效Access Token

当你需要调用MyBusiness API时,先检查当前的Access Token是否过期,如果过期就用Refresh Token刷新,再发起API请求:

// 获取当前登录用户
$user = getUser();

$client = new \Google_Client();
$client->setAuthConfig(realpath('google.json'));
$client->addScope('https://www.googleapis.com/auth/business.manage');

// 配置Refresh Token
$client->setRefreshToken($user->google_refresh_token);

// 检查Access Token是否过期,过期则刷新
if (time() > $user->google_token_expires) {
    $newTokenData = $client->fetchAccessTokenWithRefreshToken($user->google_refresh_token);
    // 更新数据库里的凭证信息
    $user->google_access_token = $newTokenData['access_token'];
    $user->google_token_expires = time() + $newTokenData['expires_in'];
    saveUser($user);
    // 给客户端设置新的Access Token
    $client->setAccessToken($newTokenData['access_token']);
} else {
    // 直接使用未过期的Access Token
    $client->setAccessToken($user->google_access_token);
}

// 现在可以正常调用API了
$service = new \Google_Service_MyBusinessAccountManagement($client);
$accounts = $service->accounts->listAccounts()->getAccounts();

额外注意事项

  • 确保你的Google Cloud项目已经启用了MyBusiness Account Management API(在API库中搜索并启用);
  • 确保你的OAuth同意屏幕里已经添加了https://www.googleapis.com/auth/business.manage这个权限范围,如果是面向外部用户的应用,还需要提交Google审核;
  • 永远不要把ID Token当成Access Token使用,两者的设计目的完全不同:ID Token用于身份验证,Access Token用于API授权。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 12:00:28