【问题标题】:Google api refresh_token null and how to refresh access tokenGoogle api refresh_token null 以及如何刷新访问令牌
【发布时间】:2016-11-22 20:53:35
【问题描述】:

我将 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 获取 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"
    

获得访问令牌后,我将其设置在数据库中。然后在行动中,我为 google api(新的 Google 客户端())创建了包装器,并将这个客户端设置为来自 DB 的访问令牌。如何刷新我的访问令牌?我尝试使用函数 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

如果在操作中我为 Google 客户端设置了一些参数,如果我添加构造函数I,这也是相同的,那么我做错了什么?

【问题讨论】:

    标签: php google-drive-api google-api-php-client


    【解决方案1】:

    OAuth 2.0 protocol 中,您的应用请求授权以访问由范围标识的资源,并且假设用户已通过身份验证并获得批准,您的应用会收到允许其访问这些资源的短期访问令牌,并且(可选)刷新令牌以允许长期访问。

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

    刷新令牌如果遭到破坏,将毫无用处,因为攻击者除了刷新令牌之外还需要客户端 ID 和密码才能获得访问令牌。

    令牌可能停止工作的原因:

    • 用户已撤销访问权限。
    • 令牌已六个月未使用。
    • 用户更改了密码,并且令牌包含 Gmail、日历、联系人或环聊范围。
    • 用户帐户已超过一定数量的令牌请求。

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

    这是一个相关的 SO 票,讨论为什么获得 NULL 令牌:Getting null Refresh token

    【讨论】:

    • 我更新了我的问题,在我的范围内三个参数,我在构造函数包装器access_type: offline approval_prompt: force 中仍然有过期的刷新令牌,如何更新或者 HWIO 包中的问题我从 HWIO 获取访问令牌。因为我对这个库有另一个问题,所以我在谷歌驱动器中上传文件,但有 emty 文件并有函数创建,但在重建项目和作曲家安装后现在丢失了。我觉得有问题(
    【解决方案2】:

    我明白。我从 HWIO 包中获取访问令牌,并在配置 HWIO 包中添加 access_type:offline,approval_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
    

    【讨论】:

      【解决方案3】:

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

      如下修改代码将在原始访问令牌中合并新的访问令牌(请参阅:array_merge)。这样您就可以保留您的 refresh_token 以供将来的请求使用。我已向 Google 提交了以下修复,希望他们在某个时候更新它。

      See docs for more info

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

      【讨论】:

        【解决方案4】:

        Arithran 已经回答了一半。

        仅在您首次授权帐户时发送过期令牌。之后您将不再收到它,这就是为什么您需要从一开始就保存它,然后在每次刷新时合并新旧数组。

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

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

        记得在您的请求中添加access_type=offline

        【讨论】:

        • 如何使用客户端 SDK JS 发出请求??
        猜你喜欢
        • 2017-06-09
        • 2012-11-26
        • 1970-01-01
        • 2016-03-13
        • 2014-07-18
        • 2020-09-13
        • 2019-06-29
        • 2016-09-12
        • 2015-11-28
        相关资源
        最近更新 更多