Google OAuth 2.0刷新令牌,用于公开访问的Web应用程序 [英] Google OAuth 2.0 refresh token for web application with public access

查看:121
本文介绍了Google OAuth 2.0刷新令牌,用于公开访问的Web应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出现以下错误:


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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆