我的第一个问题是当我制作Google_Client
的实例并设置所有需要的scopes
,configs
,access types
和others
,然后使用$client->createAuthUrl();
为用户生成一个用户的URL我允许使用谷歌帐户访问我的应用程序我是登录。一切正常,直到我需要刷新令牌。
我在下面解释令牌刷新。
$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"
}
这里没有刷新令牌。我认为这是因为谷歌在离线模式下的工作方式
用户授予对请求范围的离线访问权限后,您可以在用户离线时继续使用API客户端代表用户访问Google API。客户端对象将根据需要刷新访问令牌。
所以我将从请求获得的令牌和数据库中存储的令牌设置为Google_Client
实例
$client->setAccessToken(Auth::user()->getUserInfo()->refresh_token)
这有效。但是当令牌需要刷新时它没有得到刷新。相反,我得到了
“无效的信用卡错误”。
谷歌说:
“客户端对象将根据需要刷新访问令牌。”但这不会发生。
我不明白如果我需要调用特殊方法或Google_Client
如何处理令牌刷新。
我已经尝试使用CODE parameter
获取令牌并使用它刷新令牌。
$client->fetchAccessTokenWithAuthCode($code);
并得到这个错误:
array:2 [▼
"error" => "invalid_request"
"error_description" => "Could not determine client ID from request."
]
我可能没有做对,但我不知道是什么。说实话我很困惑。已经失去了一天没有任何成功。
只有在您第一次请求访问用户时,才会获得刷新令牌。之后,Google假定您保存了刷新令牌。
让用户转到他们的Google帐户并撤消授予此客户端应用程序的访问权限。
转到显示可访问您帐户的应用的页面:
然后让他们再次验证您的应用程序。你应该在那个时候看到刷新的方法。确保保存。
你也可以做到
$client->revokeToken();
应该撤销用户授予的访问权限。但是我没有试过这个,看它是否给我一个新的刷新令牌。
这是我刷新访问令牌的代码注意它的PHP我不是一个看起来非常接近的devvel你应该能够隐藏它,如果它没有开箱即用
/**
* 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上提出的工作
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();
}
}
根据我的经验:
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,
]);