当我尝试使用OAuth(服务帐户)更新Google日历时,返回了OAuth2令牌消息:'{“error”:“access_denied”}'

问题描述:

我正在使用Google Standard Library for PHP使用日历服务,并且已设置通过Google API控制台进行OAuth 2.0身份验证的服务帐户类型。当我尝试使用OAuth(服务帐户)更新Google日历时,返回了OAuth2令牌消息:'{“error”:“access_denied”}'

我的主要目标是通过批次更新用户的Google日历(例如:[email protected])(当用户不在线时)。例如。更新用户日历中的事件。

当用户登录应用程序(使用OAuth2.0)时,他/她将为应用程序提供“管理日历”,“查看日历”和“当我不在时执行这些操作使用应用程序”

下面的代码是用来使用OAuth2.0的

<?php 
require_once '../../src/Google_Client.php'; 
require_once '../../src/contrib/Google_CalendarService.php'; 
session_start(); 

$client = new Google_Client(); 
$client->setApplicationName("Google Calendar PHP Starter Application"); 


$client->setClientId('XXXXX-flue2a9o5ll602ovrhaejlpm9otgjh1r.apps.googleusercontent.com'); 
$client->setClientSecret('XXXXXXXXXX'); 
$client->setRedirectUri('http://localhost/testAPI/google-api-php-client/examples/calendar/simple.php'); 
$client->setDeveloperKey('AIzaSyCGvXRXGMo58ZDswyb4zBkJgRMLcHBRIrI'); 
$cal = new Google_CalendarService($client); 
if (isset($_GET['logout'])) { 
    unset($_SESSION['token']); 
} 

if (isset($_GET['code'])) { 
    $client->authenticate($_GET['code']); 

    $_SESSION['code']=$_GET['code']; 

    $_SESSION['token'] = $client->getAccessToken(); 
    header('Location: http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']); 
} 

if (isset($_SESSION['token'])) { 
    $client->setAccessToken($_SESSION['token']); 
} 

if ($client->getAccessToken()) { 
    $calList = $cal->calendarList->listCalendarList(); 
    print "<h1>Calendar List</h1><pre>" . print_r($calList, true) . "</pre>"; 

    echo $_SESSION['code']; 


$_SESSION['token'] = $client->getAccessToken(); 
} else { 
    $authUrl = $client->createAuthUrl(); 
    print "<a class='login' href='$authUrl'>Connect Me!</a>"; 
} 

?> 

一旦我得到的权限做我必须保存东西将来使用这些权限时未登录用户登录?

下面的代码,当用户登录时工作正常,但返回错误刷新的OAuth2令牌,消息:“{‘错误’:‘ACCESS_DENIED’}”当用户注销

<?php 

require_once '../src/Google_Client.php'; 
require_once '../src/contrib/Google_CalendarService.php'; 

session_start(); 

const CLIENT_ID = 'XXXXXX.apps.googleusercontent.com'; 
const SERVICE_ACCOUNT_NAME = '[email protected]'; 

const KEY_FILE = 'f183b8caXXXXXXXXatekey.p12'; 

$client = new Google_Client(); 
$client->setApplicationName("XXXXXXXX Calendar Service"); 

if (isset($_SESSION['token'])) { 
$client->setAccessToken($_SESSION['token']); 
} 

$key = file_get_contents(KEY_FILE); 
$client->setClientId(CLIENT_ID); 

$client->setAssertionCredentials(new Google_AssertionCredentials(
     SERVICE_ACCOUNT_NAME, 
     array('https://www.googleapis.com/auth/calendar'), 
     $key, 
     'notasecret', 
     'http://oauth.net/grant_type/jwt/1.0/bearer', 
     '[email protected]') 
); 

$client->setClientId(CLIENT_ID); 

$cal = new Google_CalendarService($client); 

    try{ 
$cal->events->quickAdd("[email protected]", "SERVICE TEST "); 
}catch(Exception $e){ 

    print_r($e->getMessage()); 
} 

// We're not done yet. Remember to update the cached access token. 
// Remember to replace $_SESSION with a real database or memcached. 
if ($client->getAccessToken()) { 
    echo $_SESSION['token'] = $client->getAccessToken(); 
} 

如果用户没有登录,更新日历(提供用户授权),我应该怎么做。我应该在用户登录时保存访问代码,并在以后要运行批处理时使用它?

BTW什么是关联句柄?

由于未正确提及您的范围而导致出错。在谷歌OAuth 2.0范围定义:

表明应用程序正在请求的谷歌API的访问。在此参数中传递的值 通知向 用户显示的同意页面。请求的权限数量与获得用户同意的可能性之间存在反向关系。

空间分隔设置权限的应用程序请求

  • 解决您必须首先将范围更改参数的问题

  • 包括日历范围,它

  • 然后得到访问令牌,然后尝试更改东西

  • 然后做相应的改变,以在API文档

+0

谢谢Vineeth;当用户提供他的用户名和密码并给予他的同意时,这可以正常工作。但是我想在没有用户的情况下访问日历。直接访问绕过服务帐户的登录UI。在这种情况下,我应该在哪里添加范围? – 2013-03-04 09:39:05

+0

@ RoydonD'Souza同意书给你指定的作用域。在用户重定向之前,当您要求第一次标记添加范围 – Vineet1982 2013-03-04 09:40:57

+0

@ Vineeth1982:非常感谢。它的工作。我遵循了您的建议以及'Blaine Lang'提供的步骤:https://groups.google.com/forum/?fromgroups=#!topic/google-calendar-api/MySzyAXq12Q 我得到的部分错误是因为我没有提到日历范围,也因为我没有与服务帐户共享日历。上面的链接中的详细信息。 – 2013-03-04 13:31:29

提供事实上的要求,你不需要共享与服务帐户的日历步骤。需要做的是将全域授权委派给您的服务帐户。

您现在创建的服务帐户需要被授予对您要访问的Google Apps域用户数据的访问权限。

以下任务必须由Google Apps域的管理员执行: 1.转到您的Google Apps域的控制面板。该网址应该会像:https://www.google.com/a/cpanel/mydomain.com

  1. 转到高级工具...>管理第三方OAuth客户端访问。

  2. 在客户端名称字段中输入服务帐户的客户端ID。

  3. 在一个或多个API范围字段中,输入您的应用程序应被授予访问权限的范围列表。例如,如果您需要在全域范围内只读访问Google Calendar API,请输入:https://www.googleapis.com/auth/calendar.readonly

  4. 单击授权按钮。

+0

我试过了。这是我想要实现的。但没有与服务帐户共享的日历,它会显示“禁止”您是否可以指出为使这件事发挥作用,我必须做哪些其他更改? – 2013-03-11 07:54:15