Google OAuth 2.0刷新令牌,用于公开访问的Web应用程序 [英] Google OAuth 2.0 refresh token for web application with public access
问题描述
出现以下错误:
OAuth 2.0访问令牌已过期,并且刷新令牌不可用。对于自动批准的响应,不会返回刷新令牌
我有一个只有我的服务器将访问的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上提供的文档:
https://github.com/google/google-api-php-client/blob/master/examples/service-account.php 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);
}
这将返回以下消息:
刷新OAuth2令牌时出错,消息:'{error:invalid_grant}''
跟踪此代码的源代码后,可以在 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上发现了这篇文章:
刷新OAuth2令牌的错误{error:invalid_grant}
可以看到还有没有首选的解决方案。 这让我发疯。几乎没有任何文档可用,如果有人有解决方案,我相信我不是唯一一个正在寻找它的人。
解决方案每个access_token在几秒钟后过期,需要刷新refresh_token,Offline access就是您要查找的内容。您可以在此处查看文档:
https://developers.google.com/accounts/docs/OAuth2WebServer#offline
要获取一个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:
The OAuth 2.0 access token has expired, and a refresh token is not available. Refresh tokens are not returned for responses that were auto-approved
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:
Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant" }''
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应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!