Google api refresh_token null и как обновить токен доступа

Я использую HWIO Bundle для google api, и когда у меня есть ответ от google refreshToken = null, почему? Как обновить токен

oAuthToken = {HWI\Bundle\OAuthBundle\Security\Core\Authentication\Token\OAuthToken} [11]
accessToken = "ya29.Ci8lA1JTu9CB81dOFy-nzszViRgCI2CvvKVrCd0Lq-8I0QR_dIrl-_7RccdGt1Islg"
rawToken = {array} [4]
 access_token = "ya29.Ci8lA1JTu9CB81dOFy-nzszViRgCI2CvvKVrCd0Lq-8I0QR_dIrl-_7RccdGt1Islg"
 token_type = "Bearer"
 expires_in = 3578
id_token = "xxxxx"
refreshToken = null
expiresIn = 3578
createdAt = 1468957368
tokenSecret = null
resourceOwnerName = null

потому что в google/apiclient, "version": "1.1.7" в функции требуется refresh_token

 public function getRefreshToken()
 {
  if (array_key_exists('refresh_token', $this->token)) {
    return $this->token['refresh_token'];
  } else {
    return null;
  }
 }

этот мой токен доступа

{"access_token":"ya29.Ci8lA1JTu9CB81dOFy-nzszViRgCI2CvvKVrCd0Lq-8I0QR_dIrl-_7RccdGt1Islg","token_type":"Bearer","expires_in":3578,"id_token":"xxxx","created":1468957368}

не обновить токен, потому что из google get refreshToken = null или нужно установить значение null с токеном обновления ключа или этим не согласен?

    $isExpired = $client->isAccessTokenExpired(); // true (bool Returns True if the access_token is expired.)
    $refresh = $client->getRefreshToken(); //null because not gahe refresh token 

    $client->getGoogleClient()->setAccessType ("offline"); //some  recomendation
    $client->getGoogleClient()->setApprovalPrompt ("force"); //some recomendation

    $isAgainExpired = $client->isAccessTokenExpired(); // still true (expired)

все еще есть исключение - 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 = new Google_Client(), но в оболочке, в конструкторе.
  • Я получаю токен доступа из пакета HWIO:

    hwi_oauth:
    connect:
      account_connector: app.provider.user_provider
    firewall_name: secured_area
    resource_owners:
        google:
            type:                google
            client_id:           xxx.apps.googleusercontent.com
            client_secret:       xxx
            scope:               "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/drive"
    

и после того, как я получу токен доступа, я установил его в БД. Затем в Action я создаю оболочку для google api (новый Google Client()) и устанавливаю для этого клиента мой токен доступа из БД. Как обновить токен доступа? Я пытаюсь в действии использовать функцию google api lib setAccessType и setApprovalPrompt, но не efect

public function __construct(array $config, LoggerInterface $symfonyLogger = null)
{
    // True if objects should be returned by the service classes.
    // False if associative arrays should be returned (default behavior).
    $config['use_objects'] = true;
    $client = new \Google_Client($config);
    if ($symfonyLogger) {
        //BC for Google API 1.0
        if (class_exists('\Google_Logger_Psr')) {
            $googleLogger = new \Google_Logger_Psr($client, $symfonyLogger);
            $client->setLogger($googleLogger);
        } else {
            $client->setLogger($symfonyLogger);
        }
    }
    $client -> setApplicationName($config['application_name']);
    $client -> setClientId($config['oauth2_client_id']);
    $client -> setClientSecret($config['oauth2_client_secret']);
    $client -> setRedirectUri($config['oauth2_redirect_uri']);
    $client -> setDeveloperKey($config['developer_key']);
    $client -> setAccessType ($config['access_type']);
    $client -> setApprovalPrompt ($config['approval_prompt']);

    $this -> client = $client;
}

config это:

    happy_r_google_api:
    application_name: carbon-quanta-137312
    oauth2_client_id: xxxx.apps.googleusercontent.com
    oauth2_client_secret: xxx
    oauth2_redirect_uri: null
    developer_key: null
    site_name: aog.local.com
    access_type: offline
    approval_prompt: force

и если в действии я установил в Google Client некоторые параметры, это будет одинаково, если я добавлю конструктор, так что я делаю неправильно?

Ответ 1

refresh_token возвращается только при первом запросе. Когда вы обновляете токен доступа во второй раз, он возвращает все, кроме refresh_token, а file_put_contents удаляет refresh_token, когда это происходит во второй раз.

Модификация кода следующим образом будет сливаться в исходном токене доступа с новым (см.: array_merge). Таким образом, вы сможете сохранить refresh_token для будущих запросов. Я опубликовал следующее исправление для Google, надеюсь, что они обновят его в какой-то момент.

Подробнее см. в документах

    // Refresh the token if it expired.
    if ($client->isAccessTokenExpired()) {
        $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
        $newAccessToken = $client->getAccessToken();
        $accessToken = array_merge($accessToken, $newAccessToken);
        file_put_contents($credentialsPath, json_encode($accessToken));
    }

Ответ 2

В протокол OAuth 2.0 ваше приложение запрашивает авторизацию для доступа к ресурсам, которые идентифицируются областями, и при условии, что пользователь аутентифицирован и одобряет, ваше приложение получает недолгосрочные токены доступа, которые позволяют ему обращаться к этим ресурсам и (необязательно) обновлять токены, чтобы обеспечить долгосрочный доступ.

Идея токенов обновления заключается в том, что если токен доступа скомпрометирован, потому что он недолговечен, у злоумышленника есть ограниченное окно, в котором он будет злоупотреблять им.

Обновить токены, если они скомпрометированы, бесполезны, потому что злоумышленник требует идентификатор клиента и секрет в дополнение к токере обновления, чтобы получить токен доступа.

Причина, по которой токен может перестать работать:

  • Пользователь отменил доступ.
  • токен не использовался в течение шести месяцев.
  • Пользователь изменил пароли, а токен содержит области Gmail, Календарь, Контакты или Hangouts.
  • Учетная запись пользователя превысила определенное количество запросов токенов.

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

Здесь в соответствующем бите SO обсуждаются причины получения маркера NULL: Получение нулевого токена обновления

Ответ 3

Я подставил. Я получаю токен доступа из пакета HWIO и добавляю в конфигурацию HWIO bundle access_type: offline, assert_prompt: force и в ответ я обновляю токен, но не null

    google:
        type:                google
        client_id:           xxx
        client_secret:       xxx
        scope:               "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/drive"
        options:
            access_type:         offline
            approval_prompt:     force

Ответ 4

Половина ответа уже ответила Аритран.

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

Другая половина ответа - как удалить и снова получить этот токен, иначе вам нужно будет каждый раз тестировать новую учетную запись google.

  • Перейдите в настройки безопасности своей учетной записи: https://www.google.com/settings/u/1/security.
  • Перейдите к разделу "Авторизация приложений и сайтов", затем нажмите "Просмотреть все".
  • Затем "Отменить доступ" к вашему приложению.
  • Сделайте новый запрос OAuth2. Это вернет refresh_token.

Не забудьте добавить access_type=offline к вашему запросу