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 - 解决未在递归 Promise 函数中调用的问题

java - 哪个是 hello world 的最简单的 google API?

javascript - Google Maps API,如何在整个城市或可见的整个 map 部分获取服务(文本搜索)

mysql - Laravel Eloquent Where 条件来自 2 个表

laravel - 如何在 laravel 中定义模型本身的顺序(orderBy)?

php - 如何在 Linux 上安装 Composer 以便能够运行 Laravel New 命令

php - Laravel 5.4 搜索邮政区通配符

php - 运行 Laravel Dusk 时没有输出/没有任何反应

Javascript 代码在 Blade 模板 Laravel 中无法工作

amazon-web-services - 使用 Laravel 5.3 的 Amazon SES 403 Forbidden SignatureDoesNotMatch