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

时间:2016-07-19 19:54:55

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

我使用HWIO Bundle for 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中,"版本":" 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}

没有刷新令牌,因为从go get get refreshToken = null或需要使用密钥刷新令牌或此dosn&te; t metter设置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 bundle获取访问令牌:

    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中我为google api创建包装器(新的Google Client())并将此客户端设置为来自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

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

4 个答案:

答案 0 :(得分:10)

refresh_token 仅在第一次请求时返回。当您再次刷新访问令牌时,它会返回除 refresh_token 之外的所有内容, file_put_contents 会在第二次发生时删除 refresh_token 。< / p>

如下所示修改代码将在原始访问令牌中与新代码合并(请参阅: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));
    }

答案 1 :(得分:2)

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

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

刷新令牌(如果受到攻击)是无用的,因为除了刷新令牌之外,攻击者还需要客户端ID和机密才能获得访问令牌。

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

  • 用户已撤销访问权限。
  • 该令牌已使用六个月。
  • 用户更改了密码,该令牌包含Gmail,日历,通讯录或环聊范围。
  • 用户帐户已超过一定数量的令牌请求。

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

这是一张相关的SO票据,讨论了获取NULL令牌的原因:Getting null Refresh token

答案 2 :(得分:2)

Arithran已经回答了一半答案。

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

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

  1. 转到您的帐户安全设置:https://www.google.com/settings/u/1/security
  2. 滚动到“#34;授权应用程序和网站”部分&#34;然后点击查看全部。
  3. 然后&#34;撤销访问&#34;到你的应用程序。
  4. 制作新的OAuth2请求。这将返回refresh_token。
  5. 请务必在您的请求中添加access_type=offline

答案 3 :(得分:0)

我知道。我从HWIO bundle获取访问令牌,我添加了配置HWIO bundle access_type:offline,approval_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