laravel - google-api 如何在带有 token 的离线请求中工作

标签 laravel laravel-5 google-api google-api-php-client google-oauth

我的第一个问题是,当我创建 Google_Client 的实例时并设置所有需要的scopes , configs , access typesothers然后生成一个 URL 供用户使用 $client->createAuthUrl(); 进行身份验证我允许使用我登录的谷歌帐户访问我的应用程序。一切正常,直到我需要刷新 token 。

我在下面解释一下 token 刷新。

  $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. 获取谷歌用户数据这是我得到的数据:

请求的代码

  public function redirectToGoogleProvider()
    {
        $parameters = ['access_type' => 'offline'];

        return Socialite::driver('google')
            ->scopes(["https://www.googleapis.com/auth/drive"])
            ->with($parameters)
            ->redirect();
    }
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"
}

这里没有刷新 token 。我认为这是因为谷歌在离线模式下工作的方式

After a user grants offline access to the requested scopes, you can continue to use the API client to access Google APIs on the user's behalf when the user is offline. The client object will refresh the access token as needed.

因此,我将从请求中获取并存储在数据库中的 token 设置为 Google_Client实例与

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

这有效。但是当需要刷新 token 时它不会被刷新。相反,我得到了

"Invalid creditianals error".

谷歌表示:

"The client object will refresh the access token as needed." But this is not happening.

我不明白如果我需要调用特殊方法或者Google_Client如何处理 token 刷新。

我尝试过使用 CODE parameter获取 token 并用它刷新 token 。

$client->fetchAccessTokenWithAuthCode($code);

并收到此错误:

array:2 [▼
  "error" => "invalid_request"
  "error_description" => "Could not determine client ID from request."
]

我可能没有做正确的事情,但我不知道是什么。 说实话我很困惑。已经为此浪费了一天的时间,但没有取得任何成功。

最佳答案

您只会在第一次请求用户访问权限时获得刷新 token 。之后,Google 会假设您保存了刷新 token 。

让用户转到他们的 Google 帐户并撤消授予此客户端应用程序的访问权限。

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

然后让他们再次验证您的应用程序。此时您应该会看到刷新 token 。请务必保存它。

撤销

你也许还可以这样做

$client->revokeToken();

这应该撤销用户授予的访问权限。不过,我还没有尝试过这样做,看看它是否能给我一个新的刷新 token 。

刷新访问

这是我用于刷新访问 token 的代码,注意它是 PHP,我不是一个 larvel 开发人员,它看起来非常接近,如果它不能开箱即用,您应该能够隐藏它

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

关于laravel - google-api 如何在带有 token 的离线请求中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55509751/

相关文章:

javascript - 从编辑表单中的下拉列表中显示国家/地区 Laravel 5.2

php - 找不到 Laravel 4 工作台类

Laravel 4、Composer 和 hybridauth - 如何加载额外的提供者

php - Laravel 中的多级急切加载?

javascript - 是否可以使用来自 google contacts api v3 的 javascript、json?

android - 我是否获得了验证用户的 Android 应用内订阅的正确步骤?

google-api - 将 oauth2 与 native (iOS/Android) 移动应用程序集成

laravel - MethodNotAllowedHttpException 从表单 textarea (ckeditor) 提交方程格式

php - 在邮件功能 laravel 5 中添加标题

php - Laravel 5.5 Cookie 不存储