Google OAuth 2.0 обновляет токен для веб-приложения с открытым доступом

Я получаю следующую ошибку:

Ток доступа OAuth 2.0 истек, и токен обновления недоступен. Обновить токены не возвращаются для ответов, которые были автоматически одобрены

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

require_once 'Google/Client.php'; require_once 'Google/Service/Analytics.php'; session_start(); $client = new Google_Client(); $client->setApplicationName("Client_Library_Examples"); $client->setDeveloperKey("{MY_API_KEY}"); $client->setClientId('{MY_CLIENT_ID}.apps.googleusercontent.com'); $client->setClientSecret('{MY_KEY}'); $client->setRedirectUri('{MY_REDIRECT_URI}'); $client->setScopes(array('https://www.googleapis.com/auth/gmail.readonly')); if (isset($_GET['code'])) { $client->authenticate($_GET['code']); $_SESSION['token'] = $client->getAccessToken(); $redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']; header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL)); } if (!$client->getAccessToken() && !isset($_SESSION['token'])) { $authUrl = $client->createAuthUrl(); print "<a class='login' href='$authUrl'>Connect Me!</a>"; } 

Как я могу настроить токен обновления для этого?

Редактирование 1: Я пробовал сделать это с учетной записью службы. Я следил за документацией, доступной в GitHub:

https://github.com/google/google-api-php-client/blob/master/examples/service-account.php

Мой скрипт выглядит так:

 session_start(); include_once "templates/base.php"; require_once 'Google/Client.php'; require_once 'Google/Service/Gmail.php'; $client_id = '{MY_CLIENT_ID}.apps.googleusercontent.com'; $service_account_name = '{MY_EMAIL_ADDRESS}@developer.gserviceaccount.com '; $key_file_location = 'Google/{MY_KEY_FILE}.p12'; echo pageHeader("Service Account Access"); if ($client_id == '' || !strlen($service_account_name) || !strlen($key_file_location)) { echo missingServiceAccountDetailsWarning(); } $client = new Google_Client(); $client->setApplicationName("Client_Library_Examples"); $service = new Google_Service_Gmail($client); if (isset($_SESSION['service_token'])) { $client->setAccessToken($_SESSION['service_token']); } $key = file_get_contents($key_file_location); $cred = new Google_Auth_AssertionCredentials( $service_account_name, array('https://www.googleapis.com/auth/gmail.readonly'), $key ); $client->setAssertionCredentials($cred); if($client->getAuth()->isAccessTokenExpired()) { $client->getAuth()->refreshTokenWithAssertion($cred); } 

Это возвращает следующее сообщение:

Ошибка обновления токена OAuth2, сообщение: '{"error": "invalid_grant"}' '

После отслеживания этого кода до его источника, который можно найти в Google/Auth/OAuth2.php

Этот метод, refreshTokenRequest :

 private function refreshTokenRequest($params) { $http = new Google_Http_Request( self::OAUTH2_TOKEN_URI, 'POST', array(), $params ); $http->disableGzip(); $request = $this->client->getIo()->makeRequest($http); $code = $request->getResponseHttpCode(); $body = $request->getResponseBody(); if (200 == $code) { $token = json_decode($body, true); if ($token == null) { throw new Google_Auth_Exception("Could not json decode the access token"); } if (! isset($token['access_token']) || ! isset($token['expires_in'])) { throw new Google_Auth_Exception("Invalid token format"); } if (isset($token['id_token'])) { $this->token['id_token'] = $token['id_token']; } $this->token['access_token'] = $token['access_token']; $this->token['expires_in'] = $token['expires_in']; $this->token['created'] = time(); } else { throw new Google_Auth_Exception("Error refreshing the OAuth2 token, message: '$body'", $code); } } 

Это означает, что переменная $code имеет значение NULL. Я нашел этот пост на SO:

Ошибка обновления токена OAuth2 {"error": "invalid_grant"}

И вижу, что решения по-прежнему нет. Это сводит меня с ума. На этом имеется очень мало документации, и если у кого-то есть решение, я уверен, что я не единственный, кто ее ищет.

Каждый access_token истекает через несколько секунд и нуждается в обновлении refresh_token, «автономный доступ» – это то, что вы ищете. Здесь вы можете ознакомиться с документацией:

https://developers.google.com/accounts/docs/OAuth2WebServer#offline

Чтобы получить refresh_token, вам нужно запустить этот код только один раз:

 require_once 'Google/Client.php'; $client = new Google_Client(); $client->setClientId('{MY_CLIENT_ID}.apps.googleusercontent.com'); $client->setClientSecret('{MY_KEY}'); $client->setRedirectUri('{MY_REDIRECT_URI}'); //next two line added to obtain refresh_token $client->setAccessType('offline'); $client->setApprovalPrompt('force'); $client->setScopes(array('https://www.googleapis.com/auth/gmail.readonly')); if (isset($_GET['code'])) { $credentials = $client->authenticate($_GET['code']); /*TODO: Store $credentials somewhere secure */ } else { $authUrl = $client->createAuthUrl(); print "<a class='login' href='$authUrl'>Connect Me!</a>"; } 

$credentials включает токен доступа и токен обновления. Вы должны сохранить это для получения новых токенов доступа в любое время. Поэтому, когда вы хотели позвонить в api:

 require_once 'Google/Client.php'; require_once 'Google/Service/Gmail.php'; /*TODO: get stored $credentials */ $client = new Google_Client(); $client->setClientId('{MY_CLIENT_ID}.apps.googleusercontent.com'); $client->setRedirectUri('{MY_REDIRECT_URI}'); $client->setClientSecret('{MY_KEY}'); $client->setScopes(array('https://www.googleapis.com/auth/gmail.readonly')); $client->setAccessToken($credentials); $service = new Google_Service_Gmail($client);