TL; DR
Проблема здесь в том, что я не могу выполнить fetchAccessTokenWithRefreshToken()
без предварительного выполнения setAccessToken()
, а для выполнения setAccessToken()
мне нужно знать предыдущий токен доступа.
Если я пытаюсь fetchAccessTokenWithRefreshToken()
без первого вызова setAccessToken()
, я получаю «LogicException: refre sh токен должен быть передан или установлен как часть setAccessToken»
Если я пытаюсь setAccessToken()
только со значением refresh_token
он также завершается ошибкой с Invalid token format
Единственный способ, которым он работает, - это предоставление ПОЛНОГО действительного пакета токенов аутентификации, а не только токена refre sh.
Я использую этот скрипт, чтобы получить первый аутентификатор и сгенерировать токен refre sh:
<?php
require __DIR__ . '/vendor/autoload.php';
$client = new Google_Client();
$client->setApplicationName('Gmail API Generate Refresh Token');
$client->setScopes(Google_Service_Gmail::GMAIL_MODIFY);
$client->setAuthConfig('credentials.json');
$client->setAccessType('offline');
$client->setPrompt('select_account consent');
// Request authorization from the user.
$authUrl = $client->createAuthUrl();
printf("Open the following link in your browser:\n%s\n", $authUrl);
print 'Enter verification code: ';
$authCode = trim(fgets(STDIN));
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
$client->setAccessToken($accessToken);
if (array_key_exists('error', $accessToken)) {
throw new Exception(join(', ', $accessToken));
}
print "\n\nBelow is the refresh token.\n\n";
print "Use this token with an authenticated Google_Client object to refresh auth tokens.\n";
print "This string MUST be saved otherwise you will need user approval again\n\n";
print $client->getRefreshToken();
file_put_contents('token.json', json_encode($client->getAccessToken()));
print "\n\nThe first auth token bundle has been saved to token.json\n";
Обзор
- У меня есть полностью работающее серверное приложение, которое используется для взаимодействия с почтовым ящиком Gmail одного пользователя.
- У меня есть кредиты API и токен refre sh, сохраненный в постоянном безопасном хранилище.
- Приложение может успешно взаимодействовать с Gmail до истечения срока действия токена доступа.
В целом цель состоит в том, чтобы иметь возможность взаимодействовать с API Gmail, когда приложение имеет ТОЛЬКО следующее: действительный идентификатор клиента / секретный ключ и refresh_token. Я обнаружил, что мне нужно отслеживать токены аутентификации, а также токен refre sh.
Вот проблема, с которой я сталкиваюсь:
- По истечении срока действия токена доступа я не могу сгенерировать новый, используя только мои кредиты API и refre sh маркер.
- Я получаю сообщение об ошибке
invalid_grant
, если я пытаюсь вызвать fetchAccessTokenWithRefreshToken()
, используя только строку токена refre sh в качестве параметра. - Единственный способ, которым я могу получить его, чтобы дать мне новый токен, это предоставить refre sh токен И текущую информацию о токене доступа!
- Мне нужен не только сам оригинальный токен доступа, но и значения
created
и expires_in
.
Я должен передать ему полный массив информации: [access_token, expires_in, created, refresh_token]
в противном случае он просто не будет работать!
Очевидно, что я делаю что-то здесь не так, я думаю, все, что мне нужно, это токен refre sh для генерации токенов доступа по мере необходимости.
[PHP] Вот некоторые фрагменты:
(обратите внимание, что это только dev, я не планирую жестко кодировать секреты в коде)
Вот что я бы «ожидал» для работы (это НЕ работает): Ошибка здесь invalid_grant
$client = new Google_Client();
$client->setApplicationName('Gmail API PHP Quickstart');
$client->setScopes(Google_Service_Gmail::GMAIL_MODIFY);
$client->setAuthConfig('credentials.json');
$client->setAccessType('offline');
$client->setPrompt('select_account consent');
// This is the REFRESH token
$token = '1\/\/0dKcfaketokentokentokenfaketoken-L9IriuoNveLzVQ1w4-lPfakeEPn1R1NjcOK2ISE--O1PO1yEtokenr87E';
// var_dump just for sanity to ensure this returns true
var_dump($client->isAccessTokenExpired());
if ($client->isAccessTokenExpired()) {
var_dump($client->fetchAccessTokenWithRefreshToken($token));
}
ЭТО РАБОТАЕТ, потому что я ' m загружает полный массив $token
(или это потому, что я предварительно предоставил setAccessToken () заранее.:
$token = array();
$token['access_token'] = '<<SCRUBBED_CURRENT_ACCESS_TOKEN>>>';
$token['expires_in'] = 3599;
$token['refresh_token'] = '<<SCRUBBED_REFRESH_TOKEN>>';
$token['created'] = 1587447211;
// If I leave out ANY of the values above, the token refresh does not work!
// omitted some Gmail client configuration and setup.
$this->client->setAccessToken($token);
if ($this->client->isAccessTokenExpired()) {
$this->accessToken = $this->client->fetchAccessTokenWithRefreshToken($token);
}
else {
$this->accessToken = $this->client->getAccessToken();
}
$this->service = new Google_Service_Gmail($this->client);
Подсказка:
Я заметил на https://github.com/googleapis/google-api-php-client/blob/1fdfe942f9aaf3064e621834a5e3047fccb3a6da/src/Google/Client.php#L275 fetchAccessTokenWithRefreshToken()
откатится к существующему токену, это объясняет, почему это будет работать, когда я предварительно настрою существующий токен. эта загадка, кажется, разгадана. Не объясняет, почему он все еще не работает без предустановленного токена.
Я бы ожидал, что он просто будет работать так:
// Omitted initial Gmail client setup
if ($this->client->isAccessTokenExpired()) {
$this->accessToken = $this->client->fetchAccessTokenWithRefreshToken('<MY_REFRESH_TOKEN');
}
else {
$this->accessToken = $this->client->getAccessToken();
}
$this->service = new Google_Service_Gmail($this->client);
Это тоже не работает (подтвердил, что значение getRefreshToken()
является хорошим):
$this->client->fetchAccessTokenWithRefreshToken($this->client->getRefreshToken());