OAuth 2.0访问令牌已过期,且无可用的刷新令牌。

17

我有一个基于 Web 的应用程序,使用 Google OAuth2.0 作为登录框架。它之前可以很好地运行,直到昨天。应用程序在访问令牌过期后无法获取刷新令牌。此外,“请求权限”页面已更改为“具有脱机访问权限”,而不是“了解您在 Google 上的身份”和“查看您的电子邮件”。

原本,“请求权限”页面会请求访问“了解您在 Google 上的身份”和“查看您的电子邮件”。用户注销并尝试第二次登录后,“请求权限”页面也将保持不变。

然而,直到昨天,“请求权限”页面更改为“具有脱机访问权限”。在访问令牌过期后,我收到以下错误消息:

PHP 致命错误:未捕获异常 'Google_AuthException',消息为 'OAuth 2.0 访问令牌已过期,且刷新令牌不可用。自动批准的响应不返回刷新令牌。',位于 /home2/xxxx/public_html/test/google-api-php-client/src/auth/Google_OAuth2.php 中的第 221 行

我尝试了 $client->setAccessType('online');,但仍旧出现致命错误。下面是我的代码以获取访问令牌:

    if ($client->getAccessToken()) {
      $token = $client->getAccessToken();
      $authObj = json_decode($token);
      $refreshToken = $authObj->refresh_token;
      $user = $oauth2->userinfo->get();
      $me = $plus->people->get('me');
      $email = filter_var($user['email'], FILTER_SANITIZE_EMAIL); // get the USER EMAIL ADDRESS using OAuth2

      $optParams = array('maxResults' => 100);
      $activities = $plus->activities->listActivities('me', 'public', $optParams);


      $_SESSION['access_token'] = $client->getAccessToken();
    } else {
      $authUrl = $client->createAuthUrl();
    }

我尝试搜索与我类似的问题,但是找不到。这件事发生在昨天。在此之前,我从未对代码进行任何更改。


据我所知,他们稍微改变了他们的安全管理。如果您现在授予应用程序访问权限,Google将会保存您请求的权限,并且只有在您想要新的权限或离线访问时才会再次询问您。我认为这是在更新系统时出现的暂时性错误,因为我现在没有遇到任何问题。 - user2897701
更新:你说得对,我也不能再使用刷新令牌了... - user2897701
你能告诉我如何摆脱这个吗? - Akilsree1
3个回答

18

通过他的评论,Fabian Parzefall 帮助我解决了这个问题。

这是我的脚本:

if($client->isAccessTokenExpired()) {

    $authUrl = $client->createAuthUrl();
    header('Location: ' . filter_var($authUrl, FILTER_SANITIZE_URL));

}

事实上很简单。 我不是让他点击Google Analytics API团队提供的演示脚本中所说的“连接我”按钮,而是直接将他重定向。

不确定这是否是正确/更安全的方法,但目前对我来说有效!


你能解释一下,这个解决方案是如何导致API批准你的访问令牌的吗? - Rodniko
这段代码不是真正获取访问令牌的,它只是为了防止用户每五分钟登录一次应用程序。 很抱歉,我已经很长时间没有碰过这段代码,现在无法提供帮助... - Charles G.

3
  if($client->isAccessTokenExpired()) {

     $client->authenticate();
     $NewAccessToken = json_decode($client->getAccessToken());
     $client->refreshToken($NewAccessToken->refresh_token);

    }

3
authenticate()需要传回来自认证系统的代码。 - J. LaRosee
我让它工作了,但似乎有一个无限循环,因为当页面加载时令牌一直过期。 - JBS

2

上面的答案是“正确”的,但是我在寻找放置位置时浪费了时间!所以,对于任何试图使用令牌过期示例的人,请发布此内容。

一旦您的代码完成了所需的令牌操作,并且您的客户端具有访问令牌...然后检查它是否仍然有效,如果无效,则发送重新授权请求!

// Stuff to do with getting tokens and storing in session etc...

if ($client->getAccessToken()) { // Hey! we got one!
    if($client->isAccessTokenExpired()) { // Oh! its not good - go for another
        $authUrl = $client->createAuthUrl();
        header('Location: ' . filter_var($authUrl, FILTER_SANITIZE_URL));
        exit();
    }
  try{
...
     }

我不得不取消所有保存并在重定向时传递令牌和状态的SESSION,但我不明白为什么我不能只取消保存的令牌。我怀疑状态与令牌一起使用,但我无法调查它,只能继续前进。 - imparante

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接