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

shu*_*van 4 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
Run Code Online (Sandbox Code Playgroud)

因为在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;
  }
 }
Run Code Online (Sandbox Code Playgroud)

这是我的访问令牌

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

没有刷新令牌,因为从谷歌获取refreshToken = null或需要设置null与键刷新令牌或此dos不metter?

    $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)
Run Code Online (Sandbox Code Playgroud)

还有例外 - 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"
    
    Run Code Online (Sandbox Code Playgroud)

在我获得访问令牌后,我将其设置在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;
}
Run Code Online (Sandbox Code Playgroud)

配置这是:

    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
Run Code Online (Sandbox Code Playgroud)

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

小智 10

refresh_token只返回第一个请求.当您再次刷新访问令牌时,它会返回除refresh_token之外的所有内容,并且file_put_contents会在第二次发生时删除refresh_token.

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

有关详细信息,请参阅文档

    // 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));
    }
Run Code Online (Sandbox Code Playgroud)


Abr*_*ero 7

Arithran已经回答了一半的答案。

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

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

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

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


And*_*ast 2

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

刷新令牌的想法是,如果访问令牌被泄露,由于它的生命周期很短,攻击者滥用它的时间窗口有限。

刷新令牌如果被泄露,将毫无用处,因为除了刷新令牌之外,攻击者还需要客户端 ID 和密钥才能获取访问令牌。

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

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

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

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