Google api refresh_token null以及如何刷新访问令牌


Google api refresh_token null and how to refresh access token

我将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}

没有刷新令牌,因为从谷歌得到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"
    

在我获得访问令牌后,我将其设置在DB中。然后在Action中,我为googleapi(新的GoogleClient())创建包装器,并将我从DB中的accesss令牌设置给这个客户端。如何刷新我的访问令牌?我尝试在实际操作中使用函数google api lib setAccessType和setApprovalPrompt,但不影响

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;
}

配置这是:

    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

如果在操作中,我为谷歌客户端设置了一些参数,如果我添加constructorI,这是一样的,那么我做错了什么?

refresh_token仅在第一个请求时返回。当您第二次刷新访问令牌时,它会返回除refresh_token之外的所有内容,并且当第二次出现这种情况时,file_put_contents会删除refresh_token

按照以下方式修改代码将在原始访问令牌中与新的访问令牌合并(请参见:array_merge)。这样,您就可以保留refresh_token以备将来请求。我已经向谷歌提交了以下修复程序,希望他们能在某个时候更新。

有关更多信息,请参阅文档

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

Arithran已经回答了一半的问题。

只有在您第一次授权您的帐户时,才会发送过期令牌。在那之后,您将不再收到它,这就是为什么您需要从一开始就保存它,然后在每次刷新时,合并新旧阵列。

答案的另一半是如何删除并再次接收该令牌,否则每次都需要使用新的谷歌帐户进行测试。

  1. 转到您的帐户安全设置:https://www.google.com/settings/u/1/security.
  2. 滚动至"授权应用程序和网站"部分,然后单击"全部查看"
  3. 然后"取消访问"您的应用程序
  4. 提出新的OAuth2请求。这将返回一个refresh_token

请记住将access_type=offline添加到您的请求

在OAuth 2.0协议中,您的应用程序请求授权以访问由作用域标识的资源,并且假设用户经过身份验证和批准,则应用程序将接收允许其访问这些资源的短暂访问令牌,以及(可选)刷新令牌以允许长期访问。

刷新令牌的想法是,如果访问令牌被破坏,因为它是短暂的,攻击者滥用它的窗口有限。

刷新令牌如果被破坏,则毫无用处,因为攻击者除了需要刷新令牌外,还需要客户端id和机密才能获得访问令牌。

代币可能停止工作的原因:

  • 用户已吊销访问权限
  • 该代币已经六个月没有使用了
  • 用户更改了密码,令牌包含Gmail、日历、联系人或Hangouts范围
  • 用户帐户已超过一定数量的令牌请求

目前,每个客户端每个用户帐户的刷新令牌限制为25个。如果达到限制,创建新令牌会自动使最旧的令牌失效,而不会发出警告。此限制不适用于服务帐户。

下面是一个相关的SO票证,讨论为什么获取NULL令牌:获取NULL刷新令牌

我理解。我从HWIO捆绑包中获得访问令牌,并在配置中添加HWIO捆绑集access_type:offline,approvel_prompt:force,作为响应,我有刷新令牌非空

    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