OAuth2 token, message: ‘{ “error” : “access_denied” }’ returned when I try to update Google Calendar using OAuth (Service Account)

Tags: , , , ,

I am using Google Standard Library for PHP for using Calendar Service and I have set up a Service Account type for OAuth 2.0 Authentication through Google API Console.

My main objective is to update the user’s google calendar (eg: user@organisationname.com) (when user is not online) through a batch. Eg. updating an event in the users calendar.

When the user logs in the application (using OAuth2.0) he/she will provide permission for the application to “Manage your calendars”,”View your calendars” and to “Perform these operations when I’m not using the application”

Following code is used to login using OAuth2.0

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

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

$cal = new Google_CalendarService($client);
if (isset($_GET['logout'])) {

if (isset($_GET['code'])) {


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

if (isset($_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>";


Once I get permissions do I have to save something to use these permissions in future when the user is not logged in?

Following code works fine when user is logged in. But returns Error refreshing the OAuth2 token, message: ‘{ “error” : “access_denied” }’ when user is logged out


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


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'])) {

$key = file_get_contents(KEY_FILE);

$client->setAssertionCredentials(new Google_AssertionCredentials(


$cal = new Google_CalendarService($client);

$cal->events->quickAdd("info@organisationname.com", "SERVICE TEST ");
}catch(Exception $e){


// 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();

What should I do in order to update calendar when user is not logged in (provided user has given permission). Should I save the Access Code when user is logged in and use it later when I want to run the batch?

BTW What is association handle?


You Getting the Error because of your Scopes not mentioned properly. In Google OAuth 2.0 Scope defined :

Indicates the Google API access your application is requesting. The values passed in this parameter inform the consent page shown to the user. There is an inverse relationship between the number of permissions requested and the likelihood of obtaining user consent.

space delimited set of permissions the application requests

  • To Resolve the issue you have to first Change the Scope Parameters

  • Include Calender Scope in it

  • Then Get the Access Token and then try to change the things

  • Then do changes accordingly to requirements and steps provided in API Documentation

Source: stackoverflow