问题描述
出现以下错误:
我有一个只有我的服务器将访问的Web应用程序, auth工作正常,但一小时后,上述错误消息弹出。我的脚本如下所示:
require_once'Google / Client.php';
require_once'Google / Service / Analytics.php';
session_start();
$ client = new Google_Client();
$ client-> setApplicationName(Client_Library_Examples);
$ client-> setDeveloperKey({MY_API_KEY});
$ client-> setClientId('{MY_CLIENT_ID} .apps.googleusercontent.com');
$ client-> setClientSecret('{MY_KEY}');
$ client-> setRedirectUri('{MY_REDIRECT_URI}');
$ client-> setScopes(array('https://www.googleapis.com/auth/gmail.readonly'));
if(isset($ _ GET ['code'])){
$ client-> authenticate($ _ GET ['code']);
$ _SESSION ['token'] = $ client-> getAccessToken();
$ redirect ='http://'。 $ _SERVER ['HTTP_HOST']。 $ _SERVER [ PHP_SELF];
header('Location:'。filter_var($ redirect,FILTER_SANITIZE_URL)); $!
$ b if(!$ client-> getAccessToken()&!isset($ _ SESSION ['token'])){
$ authUrl = $ client - > createAuthUrl();
print< a class ='login'href ='$ authUrl'>连接我!< / a>;
}
如何为此设置一个刷新标记?
编辑1:我也尝试使用服务帐户进行此操作。我遵循GitHub上提供的文档:
p>
我的脚本如下所示:
session_start();
include_oncetemplates / base.php;
require_once'Google / Client.php';
require_once'Google / Service / Gmail.php';
$ client_id ='{MY_CLIENT_ID} .apps.googleusercontent.com';
$ service_account_name ='{MY_EMAIL_ADDRESS}@developer.gserviceaccount.com';
$ key_file_location ='Google / {MY_KEY_FILE} .p12';
echo pageHeader(服务帐户访问);
if($ client_id ==''
||!strlen($ service_account_name)
||!strlen($ key_file_location)){
echo missingServiceAccountDetailsWarning();
}
$ client = new Google_Client();
$ client-> setApplicationName(Client_Library_Examples);
$ service = new Google_Service_Gmail($ client);
if(isset($ _ SESSION ['service_token'])){
$ client-> setAccessToken($ _ SESSION ['service_token']);
}
$ key = file_get_contents($ key_file_location);
$ cred = new Google_Auth_AssertionCredentials(
$ service_account_name,
array('https://www.googleapis.com/auth/gmail.readonly'),
$ key
);
$ client-> setAssertionCredentials($ cred);
if($ client-> getAuth() - > isAccessTokenExpired()){
$ client-> getAuth() - > refreshTokenWithAssertion($ cred);
}
这将返回以下消息:
跟踪此代码的源代码后,可以在 Google / Auth / OAuth2.php
有问题的方法 refreshTokenRequest
:
private function refreshTokenRequest ($ params)
{
$ http = new Google_Http_Request(
self :: OAUTH2_TOKEN_URI,
'POST',
array(),
$ params
);
$ http-> disableGzip();
$ request = $ this-> client-> getIo() - > makeRequest($ http);
$ code = $ request-> getResponseHttpCode();
$ body = $ request-> getResponseBody();
if(200 == $ code){
$ token = json_decode($ body,true);
if($ token == null){
抛出新的Google_Auth_Exception(不能json解码访问令牌);
}
if(!isset($ token ['access_token'])||!isset($ token ['expires_in'])){
抛出新的Google_Auth_Exception(无效的标记格式);
}
if(isset($ token ['id_token'])){
$ this-> token ['id_token'] = $ token ['id_token']] ;
}
$ this-> token ['access_token'] = $ token ['access_token'];
$ this-> token ['expires_in'] = $ token ['expires_in'];
$ this-> token ['created'] = time();
} else {
抛出新的Google_Auth_Exception(刷新OAuth2令牌时出错,消息:'$ body',$ code);
$ / code $ / pre
这意味着
$代码
变量是NULL。
我在SO上发现了这篇文章:
可以看到还有没有首选的解决方案。 这让我发疯。几乎没有任何文档可用,如果有人有解决方案,我相信我不是唯一一个正在寻找它的人。
解决方案每个access_token在几秒钟后过期,需要刷新refresh_token,Offline access就是您要查找的内容。您可以在此处查看文档:
要获取一个refresh_token,您只需运行一次该代码:
require_once'Google / Client.php';
$ client = new Google_Client();
$ client-> setClientId('{MY_CLIENT_ID} .apps.googleusercontent.com');
$ client-> setClientSecret('{MY_KEY}');
$ client-> setRedirectUri('{MY_REDIRECT_URI}');
//添加下两行以获取refresh_token
$ client-> setAccessType('offline');
$ client-> setApprovalPrompt('force');
$ client-> setScopes(array('https://www.googleapis.com/auth/gmail.readonly'));
if(isset($ _ GET ['code'])){
$ credentials = $ client-> authenticate($ _ GET ['code']);
$ b / * TODO:将$凭证存储在安全的地方* /
} else {
$ authUrl = $ client-> createAuthUrl();
print< a class ='login'href ='$ authUrl'>连接我!< / a>;
$ credentials
包含访问令牌和刷新令牌。您必须随时存储此信息以获取新的访问令牌。所以当你打电话给api时:require_once'Google / Client.php';
require_once'Google / Service / Gmail.php';
$ b / * TODO:获取存储的$凭证* /
$ client = new Google_Client();
$ client-> setClientId('{MY_CLIENT_ID} .apps.googleusercontent.com');
$ client-> setRedirectUri('{MY_REDIRECT_URI}');
$ client-> setClientSecret('{MY_KEY}');
$ client-> setScopes(array('https://www.googleapis.com/auth/gmail.readonly'));
$ client-> setAccessToken($ credentials);
$ service = new Google_Service_Gmail($ client);
I'm getting the following error:
I have a web application which only my server will be accessing, the initial auth works fine, but after an hour, the aforementioned error message pops up. My script looks like this:
require_once 'Google/Client.php'; require_once 'Google/Service/Analytics.php'; session_start(); $client = new Google_Client(); $client->setApplicationName("Client_Library_Examples"); $client->setDeveloperKey("{MY_API_KEY}"); $client->setClientId('{MY_CLIENT_ID}.apps.googleusercontent.com'); $client->setClientSecret('{MY_KEY}'); $client->setRedirectUri('{MY_REDIRECT_URI}'); $client->setScopes(array('https://www.googleapis.com/auth/gmail.readonly')); if (isset($_GET['code'])) { $client->authenticate($_GET['code']); $_SESSION['token'] = $client->getAccessToken(); $redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']; header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL)); } if (!$client->getAccessToken() && !isset($_SESSION['token'])) { $authUrl = $client->createAuthUrl(); print "<a class='login' href='$authUrl'>Connect Me!</a>"; }
How can I set up a refresh token for this?
Edit 1: I've tried doing this with a Service account as well. I followed the documentation available on GitHub:
https://github.com/google/google-api-php-client/blob/master/examples/service-account.php
My script looks like this:
session_start(); include_once "templates/base.php"; require_once 'Google/Client.php'; require_once 'Google/Service/Gmail.php'; $client_id = '{MY_CLIENT_ID}.apps.googleusercontent.com'; $service_account_name = '{MY_EMAIL_ADDRESS}@developer.gserviceaccount.com '; $key_file_location = 'Google/{MY_KEY_FILE}.p12'; echo pageHeader("Service Account Access"); if ($client_id == '' || !strlen($service_account_name) || !strlen($key_file_location)) { echo missingServiceAccountDetailsWarning(); } $client = new Google_Client(); $client->setApplicationName("Client_Library_Examples"); $service = new Google_Service_Gmail($client); if (isset($_SESSION['service_token'])) { $client->setAccessToken($_SESSION['service_token']); } $key = file_get_contents($key_file_location); $cred = new Google_Auth_AssertionCredentials( $service_account_name, array('https://www.googleapis.com/auth/gmail.readonly'), $key ); $client->setAssertionCredentials($cred); if($client->getAuth()->isAccessTokenExpired()) { $client->getAuth()->refreshTokenWithAssertion($cred); }
This returns the following message:
After tracking this code to it's source, which can be found in
Google/Auth/OAuth2.php
The method in question,
refreshTokenRequest
:private function refreshTokenRequest($params) { $http = new Google_Http_Request( self::OAUTH2_TOKEN_URI, 'POST', array(), $params ); $http->disableGzip(); $request = $this->client->getIo()->makeRequest($http); $code = $request->getResponseHttpCode(); $body = $request->getResponseBody(); if (200 == $code) { $token = json_decode($body, true); if ($token == null) { throw new Google_Auth_Exception("Could not json decode the access token"); } if (! isset($token['access_token']) || ! isset($token['expires_in'])) { throw new Google_Auth_Exception("Invalid token format"); } if (isset($token['id_token'])) { $this->token['id_token'] = $token['id_token']; } $this->token['access_token'] = $token['access_token']; $this->token['expires_in'] = $token['expires_in']; $this->token['created'] = time(); } else { throw new Google_Auth_Exception("Error refreshing the OAuth2 token, message: '$body'", $code); } }
Which means that the
$code
variable is NULL.I found this post on SO:Error refreshing the OAuth2 token { "error" : "invalid_grant" }
And can see that there is still no prefered solution. This is driving me nuts. There is very little to no documentation available on this and if anybody has a solution, I'm sure I'm not the only one looking for it.
解决方案Each access_token expires after a few seconds and need to be refreshed by refresh_token, "Offline access" is what you are looking for. Here you can follow the documentation:
https://developers.google.com/accounts/docs/OAuth2WebServer#offline
To obtain a refresh_token you have to run this code only one time:
require_once 'Google/Client.php'; $client = new Google_Client(); $client->setClientId('{MY_CLIENT_ID}.apps.googleusercontent.com'); $client->setClientSecret('{MY_KEY}'); $client->setRedirectUri('{MY_REDIRECT_URI}'); //next two line added to obtain refresh_token $client->setAccessType('offline'); $client->setApprovalPrompt('force'); $client->setScopes(array('https://www.googleapis.com/auth/gmail.readonly')); if (isset($_GET['code'])) { $credentials = $client->authenticate($_GET['code']); /*TODO: Store $credentials somewhere secure */ } else { $authUrl = $client->createAuthUrl(); print "<a class='login' href='$authUrl'>Connect Me!</a>"; }
$credentials
includes an access token and a refresh token. You have to store this to obtain new access tokens at any time. So when you wanted to make a call to api:require_once 'Google/Client.php'; require_once 'Google/Service/Gmail.php'; /*TODO: get stored $credentials */ $client = new Google_Client(); $client->setClientId('{MY_CLIENT_ID}.apps.googleusercontent.com'); $client->setRedirectUri('{MY_REDIRECT_URI}'); $client->setClientSecret('{MY_KEY}'); $client->setScopes(array('https://www.googleapis.com/auth/gmail.readonly')); $client->setAccessToken($credentials); $service = new Google_Service_Gmail($client);
这篇关于Google OAuth 2.0刷新令牌,用于公开访问的Web应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!