Google OAuth2 与离线、已安装的应用程序,我需要将我的刷新令牌与访问令牌分开存储吗?

Google OAuth2 with offline, installed app, Do I need to store my refresh token separately from the access token?

我相信我的代码可以正常工作,但我只是想了解我是否做错了什么,因为所有文档似乎都让这听起来像是一个自动过程,但我必须手动完成。请确保通读到最后以理解我真正的问题(我有很多人对我最近的问题下结论并回答错误的事情。)

我有一个 Web 应用程序,我需要我的一些脚本才能使用 Google API(php 客户端的 v2.0)执行一些经过身份验证的任务。我在命令行 from Google's documentation 上使用脚本创建了一个访问令牌。

在该代码示例中:

  1. 访问令牌已写入文件
  2. 当脚本再次 运行 时,访问令牌被读回
  3. 如果访问令牌过期,则会刷新
  4. 访问令牌文件被新刷新的访问令牌覆盖

然而,当我将其付诸实践时,系统在第一个令牌过期后出现故障,因为返回的新刷新的访问令牌中没有refresh_token

我收到的初始令牌如下所示:

{
  "access_token": "rituwyeorityweourtyoiuwrtoiuwyeorityiwuerytoiweurt",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "1\/askdhfkahsdfkasjdhfklashdkfhasdflkjf-a",
  "created": 1455921953
}

但是,刷新访问令牌时收到的所有后续访问令牌都没有 refresh_token key/value 返回,如下所示:

{
  "access_token": "askjdfhlkajsdhflkjahsldkfjhkalsjdhkflahdlfjah",
  "token_type": "Bearer",
  "expires_in": 3600,
  "created": 1455915147
}

我正在使用 offline 权限创建我的令牌 as stated in the Google documentation:

$client->setAccessType('offline');

它说(强调我的):

After a user grants offline access to the requested scopes, you can continue to use the API client to access Google APIs on the user's behalf when the user is offline. The client object will refresh the access token as needed.

当我创建客户端并从我的文件中为其提供访问令牌时,我检查访问令牌是否已过期,如果是,则尝试刷新它:

if ($client->isAccessTokenExpired()) {
    $client->refreshToken();
    $newtokenjson = json_encode($client->getAccessToken());
    file_put_contents($credentialsPath, $newtokenjson);
}

但是,新的访问令牌是没有我上面显示的 refresh_token 的那个,如果访问令牌中没有 refresh_token 密钥,那么 Google实际上不会更新我的访问权限并让我继续提出请求。

我相信我 "solved" 它通过将初始 refresh_token 除了访问令牌存储在一个单独的文件中,当我试图刷新我当前的访问令牌时我强制旧的 refresh_token 放入其中,但是我在文档中可以找到的任何地方都没有解释...

if ($client->isAccessTokenExpired()) {
    $refreshtoken = file_get_contents(REFRESH_TOKEN_PATH);
    $client->refreshToken($refreshtoken);
    $newtokenjson = json_encode($client->getAccessToken());
    file_put_contents($credentialsPath, $newtokenjson);
}

所以我觉得我正在破解一些不应该以这种方式被破解的东西,而且以后会出问题。

简而言之,我将永远重复使用每个刷新请求的初始 refresh_token

这就是我 应该 这样做的方式吗?如果是,为什么文档中从未提及或者在 Google 给出的示例代码中?

如果它在某处被提及而我错过了它,请让我知道它在哪里,这样我就可以不再担心我的代码做了一些不好的事情,当我在生产时回来咬我我们直播这个产品。

我自己是新手,不太了解它,但也许这会有所帮助。

https://developers.google.com/youtube/reporting/guides/authorization/server-side-web-apps#OAuth2_Refreshing_a_Token

看来应该存储刷新令牌。

此外,我发现如果我用下面这行代码设置approval_prompt = 'force': $client->setapprovalPrompt('force');我总是可以获得刷新令牌,但根据文档,这听起来像是个坏主意:

"Note that there are limits on the number of refresh tokens that will be issued; one limit per client/user combination, and another per user across all clients. You should save refresh tokens in long-term storage and continue to use them as long as they remain valid. If your application requests too many refresh tokens, it may run into these limits, in which case older refresh tokens will stop working."