我一整天都在处理这个问题,而我却无法弄清楚是什么问题。
我有一个使用Google Api客户端的应用程序用于javascript,它没有任何问题。现在我想在服务器端做一些事情,所以在研究了一下后,发现要走的路是在后端使用setAccessToken
方法在客户端使用令牌。
所以我尝试将我的令牌对象作为JSON(使用JSON.stringify(gapi.auth.getToken())
)发送,一旦我尝试在需要auth的后端进行API调用,我就会收到以下错误:
OAuth 2.0访问令牌已过期,并且刷新令牌不可用。对于自动批准的响应,不会返回刷新令牌。
所以,有点困惑,我尝试使用谷歌终端上的curl来解决令牌,这会返回以下内容
{
"issued_to": "client_id",
"audience": "client_id",
"user_id": "user_id",
"scope": "https://www.googleapis.com/auth/youtube.readonly https://www.googleapis.com/auth/youtube.upload https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/plus.me",
"expires_in": 1465,
"email": "user_email",
"verified_email": true,
"access_type": "online"
}
所以我知道令牌很好而且有效。我的代码设置方式如下(编辑:
<?php
// The token JSON is not inline, it comes from another source directly from the client side, but this is how it looks
$token_json = '{"state":"","access_token":"TOTALLY_VALID_ACCESS_TOKEN","token_type":"Bearer","expires_in":"3600","scope":"https://www.googleapis.com/auth/youtube.readonly https://www.googleapis.com/auth/youtube.upload https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/plus.me","client_id":"CLIENT_ID","g_user_cookie_policy":"single_host_origin","cookie_policy":"single_host_origin","response_type":"token","issued_at":"1415583001","expires_at":"1415586601","g-oauth-window":{},"status":{"google_logged_in":false,"signed_in":true,"method":"PROMPT"}}';
$OAUTH2_CLIENT_ID = 'CLIENT_ID';
$OAUTH2_CLIENT_SECRET = 'CLIENT_SECRET';
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setAccessToken($token_json);
$youtube = new Google_Service_YouTube($client);
try{
/* Random code goes here */
// Auth Exception here.
$insertRequest = $youtube->videos->insert("status,snippet", $video);
} catch (Google_Exception $e) {
var_dump($e->getMessage());
}
我是否需要设置离线访问权限?我要求登录过程必须是javascript,因此无法从后端重新创建登录流程。
我有什么遗失的吗?
答案 0 :(得分:3)
好吧,如果其他人偶然发现了这个:
显然,直接共享令牌不是可行的方法,因为不同的API包装器处理令牌的方式不同。您需要做的是将一次性代码传递给PHP并使用以下内容获取访问令牌
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
// Couldn't find this anywhere in the docs, but it's required. If you don't pass this, you will get an Origin Mismatch error.
$client->setRedirectUri('postmessage');
// Get this from javascript
$client->authenticate($ONE_TIME_CODE);
// Optionally, you might want to retrieve the token and save it somewhere else e.g. the session, as the code is only good for a single use.
$_SESSION['token'] = $client->getAccessToken();
另外,从JS你需要指定除了JS令牌之外你还需要这个一次性代码,我在其他任何地方都找不到它。
gapi.auth.authorize
的示例设置{
client_id: CLIENT_ID
scope: APP_SCOPES
cookie_policy: 'single_host_origin'
response_type: 'code token'
immediate: true
}
答案 1 :(得分:0)
非常感谢,Moustached。我也花了一整天的时间来解决这个问题。但是,我发现不是那么明显什么是一次性代码以及如何获得它,所以我决定在这里提供我的代码以防其他人遇到同样的问题:
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="https://apis.google.com/js/platform.js?onload=onGoogleAPILoad" async defer></script>
<script>
$(document).ready(function() {
var auth2;
window.onGoogleAPILoad = function() {
gapi.load('auth2', function() {
auth2 = gapi.auth2.init({ client_id: 'CLIENT_ID', scope: 'profile' });
});
};
$('button').on('click', function() {
auth2.grantOfflineAccess({'redirect_uri': 'postmessage'}).then(function(response) {
$.ajax({
method: 'POST',
url: '/auth/signin',
success: onAuthSuccess = function(response) {
// check response from your server and reload page if succeed
},
data: { code: response.code }
});
});
});
});
</script>
</head>
<body>
<button>Sign In</button>
</body>
</html>
对于后端,代码几乎相同:
$client = new Google_Client();
$client->setClientId('CLIENT_ID');
$client->setClientSecret('CLIENT_SECRET');
$client->setRedirectUri('postmessage');
$client->authenticate($code); // here is one-time code
$plus = new Google_Service_Plus($client);
$user = $plus->people->get('me');
// $user is in array, containing now id, name, etc.
这是关于该主题的article。