首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >google-api在离线请求中如何使用令牌?

google-api在离线请求中如何使用令牌?
EN

Stack Overflow用户
提问于 2019-04-04 07:05:40
回答 2查看 1.7K关注 0票数 3

我的第一个问题是,当我创建Google_Client实例并设置所有需要的scopesconfigsaccess typesothers,然后用$client->createAuthUrl();为用户生成一个URL时,我允许使用我登录的google访问我的应用程序。一切正常工作,直到我需要刷新令牌。

我将在下面解释令牌刷新.

代码语言:javascript
复制
  $this->client = new Google_Client();
            $this->client->setAuthConfig(Storage::path('secret.json'));
            $this->client->setAccessType("offline");        // offline access
            $this->client->setIncludeGrantedScopes(true);   // incremental auth
            $this->client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
            $this->client->setRedirectUri(env('APP_URL') . '/login/google/callback');

接下来我做的就是用laravel-socialite.获取谷歌用户数据--这是我得到的数据:

请求的代码

代码语言:javascript
复制
  public function redirectToGoogleProvider()
    {
        $parameters = ['access_type' => 'offline'];

        return Socialite::driver('google')
            ->scopes(["https://www.googleapis.com/auth/drive"])
            ->with($parameters)
            ->redirect();
    }
代码语言:javascript
复制
User {#466 ▼
  +token: "ya29.GmPhBiSuYJ_oKsvDTUXrj3lJR5jlEYV4x8d0ZuYZLnDJgYL-uePT_KuUkIb-OQUiWBElhm6ljfac5QhDTXYK3qjWjje1vsnZsTAJ7pXyjNAVd2buZy0a6xZCTdnLdFNMKMDMXa6bGbA"
  +refreshToken: null
  +expiresIn: 3599
  +id: "101509757451285102354"
  +nickname: null
  +name: "My name"
  +email: "My email"
  +avatar: "https://lh3.googleusercontent.com/-Qsbr3VmcZ50/AAAAAAAAAAI/AAAAAAAAAAA/ACHi3rdS2HIl3LCv5EYCmvyXulG8n-Ap7w/mo/photo.jpg"
  +user: array:12 [▶]
  +"avatar_original": "https://lh3.googleusercontent.com/-Qsbr3VmcZ50/AAAAAAAAAAI/AAAAAAAAAAA/ACHi3rdS2HIl3LCv5EYCmvyXulG8n-Ap7w/mo/photo.jpg"
}

这里没有刷新令牌。我认为这是因为google在脱机模式中的工作方式。

在用户授予对请求的作用域的脱机访问权限之后,当用户脱机时,您可以继续使用API客户端代表用户访问Google。客户端对象将根据需要刷新访问令牌。

因此,我将从请求获得的令牌设置为Google_Client实例,并将其存储在数据库中。

$client->setAccessToken(Auth::user()->getUserInfo()->refresh_token)

这个很管用。但是,当令牌需要刷新时,它不会被刷新。相反我得到了

“无效信用错误”。

谷歌说:

“客户端对象将根据需要刷新访问令牌。”但这不会发生的。

我不明白我是否需要调用一个特殊的方法,或者Google_Client如何处理令牌刷新。

我尝试使用CODE parameter来获取令牌并使用它刷新令牌。

$client->fetchAccessTokenWithAuthCode($code);

并得到了以下错误:

代码语言:javascript
复制
array:2 [▼
  "error" => "invalid_request"
  "error_description" => "Could not determine client ID from request."
]

我可能做得不对,但我不知道是什么。老实说我很困惑。在这件事上已经浪费了一天,但没有取得任何成功。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-04-04 07:51:45

只有在第一次请求用户访问时才会得到刷新令牌。之后,Google假设您保存了刷新令牌。

让用户进入他们的google帐户并撤销授予这个客户端应用程序的访问权限。

转到显示具有帐户访问权限的应用程序的页面:

然后让他们再次验证您的应用程序。你应该会看到那个时候的刷新。一定要保存下来。

撤销

你也可以

代码语言:javascript
复制
$client->revokeToken();

它应该会撤销用户授予的访问权限。但是,我还没有尝试过这样做,看它是否为我提供了一个新的刷新令牌。

刷新存取

这是我刷新访问令牌的代码,注意它的PHP,我不是一个大开发器,它看起来非常接近,如果它不能正常工作,你应该能够隐藏它。

代码语言:javascript
复制
/**
 * Authenticating to Google using Oauth2
 * Documentation:  https://developers.google.com/identity/protocols/OAuth2
 * Returns a Google client with refresh token and access tokens set. 
 *  If not authencated then we will redirect to request authencation.
 * @return A google client object.
 */
function getOauth2Client() {
    try {

        $client = buildClient();

        // Set the refresh token on the client. 
        if (isset($_SESSION['refresh_token']) && $_SESSION['refresh_token']) {
            $client->refreshToken($_SESSION['refresh_token']);
        }

        // If the user has already authorized this app then get an access token
        // else redirect to ask the user to authorize access to Google Analytics.
        if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {

            // Set the access token on the client.
            $client->setAccessToken($_SESSION['access_token']);                 

            // Refresh the access token if it's expired.
            if ($client->isAccessTokenExpired()) {              
                $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
                $client->setAccessToken($client->getAccessToken()); 
                $_SESSION['access_token'] = $client->getAccessToken();              
            }           
            return $client; 
        } else {
            // We do not have access request access.
            header('Location: ' . filter_var( $client->getRedirectUri(), FILTER_SANITIZE_URL));
        }
    } catch (Exception $e) {
        print "An error occurred: " . $e->getMessage();
    }
}
票数 2
EN

Stack Overflow用户

发布于 2019-06-15 00:22:21

让我分享一下我在Laravel最后想出的东西,让它发挥作用。

代码语言:javascript
复制
public static function getOauth2Client($o_user, $f_client) {
    try {
        $o_client = new Google_Client();
        $o_client - >setAuthConfig($f_client);
        $o_client - >setAccessType('offline');
        $o_client - >setIncludeGrantedScopes(true);
        $i_token_remaining = ($o_user - >gdrive_access_ttl - (time() - $o_user - >gdrive_access_created));
        $google_client_token = ['refresh_token' = >$o_user - >gdrive_refresh_token, 'access_token' = >$o_user - >gdrive_access_token, 'created' = >$o_user - >gdrive_access_created, 'expires_in' = >$i_token_remaining, ];
        $o_client - >setAccessToken(json_encode($google_client_token));

        #token validity time is less than 60 seconds
        if ($i_token_remaining < 60 || $o_client - >isAccessTokenExpired()) {
            $res = $o_client - >fetchAccessTokenWithRefreshToken($o_client - >getRefreshToken());
            $o_user - >gdrive_access_token = $res['access_token'];
            $o_user - >gdrive_access_created = time();
            $o_user - >gdrive_access_ttl = $res['expires_in'];
        }
        return $o_client;
    } catch(Exception $e) {
        print 'An error occurred: '.$e - >getMessage();
    }
}

根据我的经验:

  • setAccessToken不会只使用令牌,它需要我的"expires_in“
  • $o_client->isAccessTokenExpired()总是返回true,除非$google_client_token提供了"created“,因为到期时考虑了"created”
  • isAccessTokenExpired在过期前检查30秒,这样我的60秒检查就可以安全地移除了。
  • $o_user是用户对象,例如用户::查找($i_user_id);
  • 刷新令牌从不更改,它只设置一次和永远,只有当请求刷新时才会更改访问令牌。
  • 访问令牌ttl是3600 -猜猜为什么?)-所以请存储和更新访问令牌。
  • 在此函数的范围之外,一旦访问令牌更改,我也会更新我的数据库。
代码语言:javascript
复制
User::updateOrCreate(
    ['email' => $o_user - > email],
    [
        'gdrive_access_token' => $o_user - > gdrive_access_token,
        'gdrive_access_created' => $o_user - > gdrive_access_created,
        'gdrive_access_ttl' => $o_user - > gdrive_access_ttl,
    ]);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55509751

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档