0

I'm working on a cron script to check my Google calendar on a daily basis. I'd like to know if it's possible to use Application-Specific Passwords (see: https://support.google.com/accounts/answer/185833?hl=it) and insert the generated password in my script. The OAUTH requires the user interaction and since I'm working on a script I cannot follow that way. I've also read about the "service accounts", but hope I could avoid it just by using Application-Specific Passwords. What's the difference? Any hint?

Many thanks Francesco

EDIT1: The code I'm trying with:

<?php
require __DIR__ . '/vendor/autoload.php';

$client = new Google_Client();
//The json file you got after creating the service account
putenv('GOOGLE_APPLICATION_CREDENTIALS=test-calendario-268115-5452ff6f57e8.json');
$client->useApplicationDefaultCredentials();
$client->setApplicationName("test_calendar");
$client->setScopes(Google_Service_Calendar::CALENDAR);
$client->setAccessType('offline');

$service = new Google_Service_Calendar($client);

$calendarList = $service->calendarList->listCalendarList();

EDIT2: $service->calendarList->listCalendarList() gives empty list use:

<?php
require __DIR__ . '/vendor/autoload.php';

$client = new Google_Client();
//The json file you got after creating the service account
putenv('GOOGLE_APPLICATION_CREDENTIALS=test-calendario-268115-5452ff6f57e8.json');
$client->useApplicationDefaultCredentials();
$client->setApplicationName("test_calendar");
$client->setScopes(Google_Service_Calendar::CALENDAR);
$client->setAccessType('offline');

$service = new Google_Service_Calendar($client);

$listEvents = $service->events->listEvents("...@group.calendar.google.com");// taken from sharing calendar settings
$events = $listEvents->getItems();
print_r($events);

Francesco
  • 1
  • 2
  • have you enabled 2-Step-Verification? – Aerials Feb 14 '20 at 12:56
  • Yes, I do... I've generated a new 16 chars password following the instructions in the link – Francesco Feb 14 '20 at 13:05
  • Service accounts are designed for server-server interaction. I believe this is your case, (cron-Calendar API). Have a read through this [Using OAuth 2.0 for Server to Server Applications](https://developers.google.com/identity/protocols/OAuth2ServiceAccount) – Aerials Feb 14 '20 at 13:15

2 Answers2

0

There are two ways to authenticate to the Google Calendar API

  • OAuth2 prompt user for access. (Not intended server-server interaction but can be done if a refresh token is generated by a user and then stored where the server can access it later.)
  • Using authorized service account credentials. (Ideal for server-server).

There is no other way to access a users data you must have their permission.

Look into Using OAuth 2.0 for Server to Server Applications.

service account

require_once __DIR__ . '/vendor/autoload.php';

// Use the developers console and download your service account
// credentials in JSON format. Place the file in this directory or
// change the key file location if necessary.
putenv('GOOGLE_APPLICATION_CREDENTIALS='.__DIR__.'/service-account.json');

/**
 * Gets the Google client refreshing auth if needed.
 * Documentation: https://developers.google.com/identity/protocols/OAuth2ServiceAccount
 * Initializes a client object.
 * @return A google client object.
 */
function getGoogleClient() {
    return getServiceAccountClient();
}

/**
 * Builds the Google client object.
 * Documentation: https://developers.google.com/api-client-library/php/auth/service-accounts
 * Scopes will need to be changed depending upon the API's being accessed. 
 * array(Google_Service_Analytics::ANALYTICS_READONLY, Google_Service_Analytics::ANALYTICS)
 * List of Google Scopes: https://developers.google.com/identity/protocols/googlescopes
 * @return A google client object.
 */
function getServiceAccountClient() {
    try {   
        // Create and configure a new client object.        
        $client = new Google_Client();
        $client->useApplicationDefaultCredentials();
        $client->addScope([YOUR SCOPES HERE]);
        return $client;
    } catch (Exception $e) {
        print "An error occurred: " . $e->getMessage();
    }
}

code ripped from ServiceAccount.php

Community
  • 1
  • 1
Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
  • OK. I've tried to follow another tread about it and it doesn't work for me (link: https://stackoverflow.com/questions/50656151/adding-an-event-to-google-calendar-using-php). I don't have to write calendar, but just read it ... I'm not sure if I can read it as a public accessible calendar and abandon the caleandar API. – Francesco Feb 14 '20 at 13:06
  • I cannot retrieve any calendar with the provided example – Francesco Feb 14 '20 at 13:09
  • Remember a service account is NOT you. By default you will be accessing the service accounts google calendar account which probably has nothing on it. YOu need to take the service account email id and share your own calendar with it then it will have access to that calendar as well. – Linda Lawton - DaImTo Feb 14 '20 at 13:14
  • I followed exactly the example and added the fake email to my calendar sharing settings... But i can only get an empty of "items" with: $service->calendarList->listCalendarList() – Francesco Feb 14 '20 at 13:22
  • Can you provide the code you are using to generate a JWTClient ? Usually this is the confusing part. Remove sensitive data b4 posting. And post it as an edit to your question please – Aerials Feb 14 '20 at 13:33
  • @Francesco theres service accounts are not going to seen anything in calendarlist.list unless you add it there first. but if you do something like a calendar.get on the calendar id you should get a response if you have shared it with the service account. – Linda Lawton - DaImTo Feb 14 '20 at 13:39
  • @DalmTo I found the problem: listCalendarList gives empty items array, but if I use the id taken from my account this way: $listEvents = $service->events->listEvents("....@group.calendar.google.com"); $events = $listEvents->getItems(); print_r($events); it works – Francesco Feb 14 '20 at 13:47
  • @DalmTo is it a bug in the Google Calendar API? – Francesco Feb 14 '20 at 13:47
  • Thats a good question there is debate about this. I have personally never seen anything added to calendarlist.list for a service account unless i do it manually. Others have reported that it "used to work" as far as i know no one has added it as an issue yet. I have been using the API on and off for about seven years. They have been making changes lately. so it could be a bug – Linda Lawton - DaImTo Feb 14 '20 at 13:52
  • OK. I'd be interested in knowing more about this issue and possible solutions... Should I open a bug report somewhere? Or can you do it? – Francesco Feb 14 '20 at 13:55
  • https://issuetracker.google.com/issues?q=componentid:191627%2B <-- if you do post one let me know and i will follow it or try to find someone at google to ping about it. – Linda Lawton - DaImTo Feb 14 '20 at 14:00
  • @DaImTo Ty, will do. Final question can I add my service account email to a different gmail account? I have 2 emails to check... Do I need 2 service account? – Francesco Feb 14 '20 at 14:02
  • The service account is created on google developer console. You can share any calendar you want with it by simply sharing the the calendar with the service account email address. As for who owns the project on google developer console look around you can add other users to it. – Linda Lawton - DaImTo Feb 14 '20 at 14:09
0

You seem to be running into this situation, which is mentioned in this Calendar help page.

Keep in mind it also applies to service accounts.

enter image description here

The accepted answer to this question...

Explains well that you can use the CalendarList: insert method to add the calendar to the calendar list.

Aerials
  • 4,231
  • 1
  • 16
  • 20