如何使用自动批准的响应获取refresh_token?

时间:2014-05-29 18:43:15

标签: oauth-2.0 google-drive-api google-api-php-client

我有以下代码:

if (isset($_REQUEST['logout']))
{
  unset($_SESSION['upload_token ']);
}

if (isset($_GET['code']))
{
  $client->authenticate($_GET['code']);
  $_SESSION['upload_token'] = $client->getAccessToken();
  $redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
  header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
}

if (isset($_SESSION['upload_token']) && $_SESSION['upload_token'])
{
  $client->setAccessToken($_SESSION['upload_token']);
  if ($client->isAccessTokenExpired())
  {
    echo "The access token is expired.<br>"; // Debug
    $client->refreshToken(json_decode($_SESSION['upload_token']));
    unset($_SESSION['upload_token']);
  }
}
else
{
  $authUrl = $client->createAuthUrl();
}

并且收到以下错误:

Uncaught exception 'Google_Auth_Exception' with message 'The OAuth 2.0 access token has expired, and a refresh token is not available. Refresh tokens are not returned for responses that were auto-approved.'

我假设我收到此错误,因为响应已自动批准。

应该改变什么?

更新:我已经尝试将其添加到我的代码中:

$client->setAccessType("online");
$client->setApprovalPrompt("auto");

基于this question。我仍然收到丢失刷新令牌的相同错误。

更新:kroikie更新后,我的代码如下所示:

$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setRedirectUri($redirect_uri);
$client->addScope("https://www.googleapis.com/auth/drive");
$client->setAccessType("offline");
$client->setApprovalPrompt("auto");
$client->setApplicationName("Appraisal App");
$service = new Google_Service_Drive($client);

if (isset($_REQUEST['logout']))
{
  unset($_SESSION['upload_token ']);
}

if (isset($_GET['code']))
{
  $resp = $client->authenticate($_GET['code']);
  $_SESSION['upload_token'] = $client->getAccessToken();
  $array = get_object_vars(json_decode($resp));
  // store and use $refreshToken to get new access tokens
  $refreshToken = $array['refreshToken'];
  $redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
  header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
}

if (isset($_SESSION['upload_token']) && $_SESSION['upload_token'])
{
  $client->setAccessToken($_SESSION['upload_token']);
  if ($client->isAccessTokenExpired())
  {
    echo "The access token is expired.  Let Raph know that you saw this.<br>";
    $client->refreshToken($refreshToken);
    unset($_SESSION['upload_token']);
  }
}
else
{
  $authUrl = $client->createAuthUrl();
}

不幸的是,当需要刷新令牌时,我仍会收到同样的致命错误。

3 个答案:

答案 0 :(得分:6)

当访问类型脱机时,当用户首次授予数据访问权限时,将返回访问令牌和刷新令牌。访问令牌可用于访问用户的数据,并且存储刷新令牌并用于在初始访问令牌过期时获取新的访问令牌。

所以尝试使用离线访问类型

$client->setAccessType('offline');

并使用刷新令牌刷新客户端的访问令牌

// $refreshToken is retrieved from the response of the
// user's initial granting access
$client->refreshToken($refreshToken)

更新: 要获取刷新令牌,请使用以下内容:

if (isset($_GET['code'])) {
  $resp = $client->authenticate($_GET['code']);
  $_SESSION['token'] = $client->getAccessToken();
  $array = get_object_vars(json_decode($resp));
  // store and use $refreshToken to get new access tokens
  $refreshToken = $array['refreshToken'];
}

答案 1 :(得分:0)

假设您要使用离线访问类型,您有两种选择:强制批准提示(因此您永远不会获得自动批准的响应):

$client->setAccessType("offline");
$client->setApprovalPrompt("force");

或者您忽略刷新令牌,只需在当前令牌过期时获得新的自动批准授权。我从未测试过这个,但由于批准不需要用户操作,我认为它有效。

您可以在此处详细了解(更改#3:服务器端自动批准):http://googlecode.blogspot.ca/2011/10/upcoming-changes-to-oauth-20-endpoint.html

答案 2 :(得分:0)

有时似乎错误出现在代码中,但在我的情况下却没有。

我遇到了同样的问题并尝试了所有类型的解决方案,但错误发生在console.developers.google.com配置中。

我认为没有必要在凭据配置中确认域。

所以当我这样做时,代码就停止了错误。