【问题标题】:OAuth2 token, message: '{ "error" : "access_denied" }' returned when I try to update Google Calendar using OAuth (Service Account)OAuth2 令牌,当我尝试使用 OAuth(服务帐户)更新 Google 日历时返回消息:'{"error":"access_denied"}'
【发布时间】:2020-03-15 20:21:49
【问题描述】:

我正在使用 Google 标准库 for PHP 来使用日历服务,并且我已经通过 Google API 控制台为 OAuth 2.0 身份验证设置了服务帐户类型。

我的主要目标是通过批量更新用户的谷歌日历(例如:user@organisationname.com)(当用户不在线时)。例如。更新用户日历中的事件。

当用户登录应用程序(使用 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 令牌时出错,消息:'{ "error" : "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 = 'XXXX@developer.gserviceaccount.com';

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',
        '363183053@developer.gserviceaccount.com')
);

$client->setClientId(CLIENT_ID);

$cal = new Google_CalendarService($client);

    try{
$cal->events->quickAdd("info@organisationname.com", "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 什么是关联句柄?

【问题讨论】:

    标签: php google-api oauth-2.0 google-calendar-api service-accounts


    【解决方案1】:

    事实上,您不需要与服务帐户共享日历。需要做的是将域范围的权限委托给您的服务帐户。

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

    以下任务必须由 Google Apps 域的管理员执行: 1. 转到您的 Google Apps 域的控制面板。 URL 应如下所示: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. 点击授权按钮。

    【讨论】:

    • 我试过这个。这就是我想要达到的目标。但是如果没有与服务帐户共享日历,它会显示“禁止”您能指出我必须做哪些其他更改才能使这件事正常工作吗?
    【解决方案2】:

    由于未正确提及您的范围而导致错误。在 Google OAuth 2.0 Scope 中定义:

    表示您的应用程序请求的 Google API 访问权限。这 在此参数中传递的值会通知显示给 用户。数量之间存在反比关系 请求的权限以及获得用户同意的可能性。

    应用程序请求的以空格分隔的权限集

    • 要解决此问题,您必须首先更改范围参数

    • 在其中包含日历范围

    • 然后获取访问令牌,然后尝试更改内容

    • 然后根据 API 文档中提供的要求和步骤进行相应的更改

    【讨论】:

    • 感谢 Vineeth;当用户提供他的用户名和密码并表示同意时,这很好。但我想在没有用户的情况下访问日历。从服务帐户绕过登录 UI 直接访问。在这种情况下我应该在哪里添加范围?
    • @RoydonD'Souza 同意您指定的范围。当您请求第一次令牌时,在用户被重定向之前添加范围
    • @Vineeth1982:非常感谢。它的工作。我遵循了您的建议以及“Blaine Lang”提供的步骤:groups.google.com/forum/?fromgroups=#!topic/google-calendar-api/… 我收到错误的部分原因是我没有提到日历范围,也因为我没有与服务帐户共享日历。上面链接中的详细信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-09
    • 2014-08-17
    • 1970-01-01
    • 2023-01-02
    • 2020-05-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多