Как получить refresh_token с автоматически одобренным ответом?

У меня есть следующий код:

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");

На основе этого вопроса . Я все еще получаю ту же ошибку об отсутствии токена обновления.

ОБНОВЛЕНИЕ: после обновления 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();
}

К сожалению, я все еще получаю ту же фатальную ошибку, когда требуется токен обновления.


person Raphael Rafatpanah    schedule 29.05.2014    source источник


Ответы (3)


Если тип доступа автономный, маркер доступа и маркер обновления возвращаются, когда пользователь впервые предоставляет доступ к данным. Маркер доступа можно использовать для доступа к данным пользователя, а маркер обновления сохраняется и используется для получения нового маркера доступа по истечении срока действия маркера первоначального доступа.

Поэтому попробуйте использовать автономный тип доступа

$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'];
}
person Arthur Thompson    schedule 02.06.2014
comment
Нужно ли сохранять $refreshToken ранее или он уже определен? Если он не определен, как бы я его определил? - person Raphael Rafatpanah; 02.06.2014
comment
Обновленный ответ с более подробной информацией. - person Arthur Thompson; 03.06.2014
comment
Спасибо за обновление, к сожалению, я все еще получаю ту же ошибку. Я разместил весь свой код. Что мне не хватает? Спасибо за вашу помощь. - person Raphael Rafatpanah; 12.06.2014
comment
У меня тоже есть эта проблема. не могли бы вы опубликовать ответ о том, как вы, наконец, решили это? Спасибо. - person Rodniko; 16.10.2014
comment
У меня тоже есть эта проблема. Я попытался включить приведенный выше код, но для меня этот раздел никогда не выполняется, потому что параметр «код» НЕ установлен. - person Rob Cranfill; 12.12.2014

Предполагая, что вы хотите использовать автономный тип доступа, у вас есть два варианта: либо вы принудительно запрашиваете подтверждение (чтобы вы никогда не получали автоматически одобренный ответ):

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

Или вы игнорируете токен обновления и просто получаете новую автоматически одобренную авторизацию, когда срок действия вашего текущего токена истек. Я никогда не проверял это, но, поскольку для утверждения не требуется никаких действий пользователя, я предполагаю, что это работает.

Подробнее об этом можно прочитать здесь (Изменение № 3: автоматическое одобрение на стороне сервера): http://googlecode.blogspot.ca/2011/10/upcoming-changes-to-oauth-20-endpoint..html

person Patrick Fournier    schedule 06.07.2015

Иногда кажется, что ошибка в коде, но в моем случае ее не было.

У меня была та же проблема, и я пробовал все виды решений, но ошибка была в конфигурации console.developers.google.com.

Я думал, что не нужно подтверждать домен в конфигурации Credentials.

Итак, когда я это сделал, код перестал выдавать ошибку.

person Rocky    schedule 22.10.2015