2016-01-26 8 views
1

Я пытаюсь подключить свой webapp к Google Drive. Поэтому я использую PHP с официальным кодом клиента Github PHP [https://github.com/google/google-api-php-client/tree/v1-master].Google API: refresh_token missing (access type = offline)

Я следовал за быстрым стартом [https://developers.google.com/drive/v2/web/quickstart/php] для v2, потому что PHP-клиент только для v2.

Затем я добавил строку для запроса автономного доступа. [См https://developers.google.com/identity/protocols/OAuth2WebServer#offline]

Мое приложение код, разработанный с использованием Yii 1, но это не важно, это:

$client = new Google_Client(); 
    $client->setApplicationName("Google Drive Client"); 
    $client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY); 
    $client->setRedirectUri(Yii::app()->createAbsoluteUrl("site/googleApiLoginCallback"));  

    $client->setAuthConfigFile(CLIENT_SECRET_PATH); 
    $client->setAccessType('offline'); 

    if (file_exists(CREDENTIALS_PATH)) { 
     $accessToken = file_get_contents(CREDENTIALS_PATH); 
    } else { 
     // Request authorization from the user. 
     $auth_url = $client->createAuthUrl(); 
     header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL)); 
     Yii::app()->end(); 
    } 
    $client->setAccessToken($accessToken); 

    // Refresh the token if it's expired. 
    if ($client->isAccessTokenExpired()) { 
     $refresh_token = $client->getRefreshToken(); 
     // CVarDumper::dump($refresh_token,2,true); 
     $client->refreshToken($refresh_token); 
     file_put_contents(CREDENTIALS_PATH, $client->getAccessToken()); 
    } 
    return $client; 

Это код для обработки OAuth обратного вызова. Я просто установил полученный токен доступа, а затем перенаправил его на страницу.

public function actionGoogleApiLoginCallback($code) 
{ 
    $client = new Google_Client(); 
    $client->setApplicationName("Google Drive Client"); 
    $client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY); 
    $client->setRedirectUri(Yii::app()->createAbsoluteUrl("site/googleApiLoginCallback"));  

    $client->setAuthConfigFile(CLIENT_SECRET_PATH); 
    $client->setAccessType('offline'); 

    $accessToken = $client->authenticate($code); 
    if(!file_exists(dirname(CREDENTIALS_PATH))) { 
     mkdir(dirname(CREDENTIALS_PATH), 0700, true); 
    } 
    file_put_contents(CREDENTIALS_PATH, $accessToken); 

    $preGoogleApiLoginRoute = Yii::app()->user->getState("preGoogleApiLoginRoute", null); 
    if ($preGoogleApiLoginRoute) 
    { 
     $this->redirect(array($preGoogleApiLoginRoute)); 
    } else { 
     $this->redirect(array("site/index")); 
    } 
} 

Когда пользователь впервые попадает на страницу, мой webapp успешно перенаправляется на Google Login; пользователь делает логин и Google перенаправляет пользователя на мой сайт по адресу site/googleApiLoginCallback. Я установил полученный код как accessToken и перенаправил пользователя на страницу webapp, откуда он пришел.

Это работает.

НО: Через некоторое время, когда пользователь вернется на страницу, токен истек. Когда он выполнил $client->getRefreshToken(), он возвращает null, так $client->refreshToken() бросить следующее сообщение об ошибке из-за отсутствие обновления маркеров

Ошибки при обновлении маркеров OAuth2, сообщение: «{„ошибка“:„invalid_request“,„error_description“: «Отсутствует требуемый параметр: refresh_token»} '

Что мне не хватает или что-то не так?

Для справки: это мой токен доступа json. Как вы можете видеть, что я имею не поле с именем «refreshToken», как я ожидаю,

{"access_token":"...hiddden...","token_type":"Bearer","expires_in":3600,"created":1453759023} 
+1

Вы не должны публиковать свой токен доступа ... По крайней мере, скрыть его часть ... :-) – MarcoS

+0

@MarcoS: он был изменен немного, это неправда ... спасибо за waring .. Я снова изменю .....! – realtebo

+1

ОК., Извините ... :-) – MarcoS

ответ

0

Из this StackOverflow question я вижу, что заявление

, чтобы получить новый refresh_token после его получения, вам нужно будет отправить своего пользователя обратно через подсказку, которую вы можете сделать, установив approval_prompt в force.

Адрес: to this old blog post от Google.

Поэтому я добавил

$client->setApprovalPrompt('force'); 

после

$client->setAccessType('offline'); 

И теперь я с перезагрузкой фишку.

0

Я использую немного другую логику, но она работает ... :-)
Вместо:

... 
$accessToken = file_get_contents(CREDENTIALS_PATH); 
... 
$client->setAccessToken($accessToken); 
if ($client->isAccessTokenExpired()) { 
    $refresh_token = $client->getRefreshToken(); 
    $client->refreshToken($refresh_token); 
    file_put_contents(CREDENTIALS_PATH, $client->getAccessToken()); 
} 
... 

я:

... 
$accessToken = file_get_contents(CREDENTIALS_PATH); 
... 
$client->setAccessToken($accessToken); 
if (!$client->getAccessToken()) { 
    die('invalid access token in ' . CREDENTIALS_PATH); 
} 
if ($client->isAccessTokenExpired()) { 
    $refresh_token = json_decode($accessToken)->refresh_token; 
    $client->refreshToken($refresh_token); 
} 
... now we are authenticated ... 
+0

проблема в том, что в моем json 'accessToken' нет поля' refresh_token' ... Как его получить? Я добавил свой токен доступа (подделанный немного) на мой вопрос, – realtebo

+0

См. Https://developers.google.com/identity/protocols/OAuth2WebServer – MarcoS

+0

спасибо, но в документе отсутствует: он не говорит о необходимость «утверждения_проблема» – realtebo

Смежные вопросы