Inserting Google Calendar Entries with Service Account
I figured this out. Since I don't see any complete examples of using service accounts with API v3, I'm just going to post my complete solution for reference. There are a few of things that you need to do in addition to implementing the code, however:
1) You need to go to the Google Developer's console and mark your account as a 'service account'. This will differentiate it from a web application. The important difference is that nobody will be prompted to log in to their account before the events are added since the account will belong to your application, not an end user. For more information see this article, starting on page 5.
2) You need to create a public/private key pair. From the developer's console, click on Credentials. Under you service account, click on 'Generate new P12 key'. You'll need to store this somewhere. That file location becomes the $key_file_location
variable string in the code below.
3) Also from the developer's console, you need to enable the Calendar
API. From your project, on the left margin you'll see APIs
. Select that and find the Calendar
API. Click it, accept the terms of service, and verify that it is now displayed under Enabled APIs
with a status of On
4) In Google Calendar that you want to add events to, under settings, click Calendar Settings then on 'Share this Calendar' at the top. Under 'Share with specific people' in the 'Person' field, paste in the email address from the service account credentials. Change the permission settings to 'Make changes to events'. Don't forget to save the change.
Then, implement this code somewhere.
Comment if something is confusing or omitted. Good luck!
<?php
function calendarize ($title, $desc, $ev_date, $cal_id) {
session_start();
/************************************************
Make an API request authenticated with a service
account.
************************************************/
set_include_path( '../google-api-php-client/src/');
require_once 'Google/Client.php';
require_once 'Google/Service/Calendar.php';
//obviously, insert your own credentials from the service account in the Google Developer's console
$client_id = '843319906820-xxxxxxxxxxxxxxxxxxxdcqal54p1he6.apps.googleusercontent.com';
$service_account_name = '843319906820-xxxxxxxxxxxxxxxxxxxdcqal54p1he6@developer.gserviceaccount.com';
$key_file_location = '../google-api-php-client/calendar-xxxxxxxxxxxx.p12';
if (!strlen($service_account_name) || !strlen($key_file_location))
echo missingServiceAccountDetailsWarning();
$client = new Google_Client();
$client->setApplicationName("Whatever the name of your app is");
if (isset($_SESSION['service_token'])) {
$client->setAccessToken($_SESSION['service_token']);
}
$key = file_get_contents($key_file_location);
$cred = new Google_Auth_AssertionCredentials(
$service_account_name,
array('https://www.googleapis.com/auth/calendar'),
$key
);
$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($cred);
}
$_SESSION['service_token'] = $client->getAccessToken();
$calendarService = new Google_Service_Calendar($client);
$calendarList = $calendarService->calendarList;
//Set the Event data
$event = new Google_Service_Calendar_Event();
$event->setSummary($title);
$event->setDescription($desc);
$start = new Google_Service_Calendar_EventDateTime();
$start->setDateTime($ev_date);
$event->setStart($start);
$end = new Google_Service_Calendar_EventDateTime();
$end->setDateTime($ev_date);
$event->setEnd($end);
$createdEvent = $calendarService->events->insert($cal_id, $event);
echo $createdEvent->getId();
}
?>
Some helpful resources:
Github example for service accounts
Google Developers Console for inserting events in API v3
Using OAuth 2.0 to Access Google APIs
Creating Google Calendar events with a GCP Service Account
Answer:
You need to enable the APIs and provide scopes in three places: in your auth code, in the GCP console, and the Google Admin console.
More Information:
As I explained in the comments, the code you have provided should run without issue. The Insufficient Permission: Request had insufficient authentication scopes.
error is a result of the service account not being given access to the required scopes somewhere on Google's side.
Make sure you have completed the following steps:
- Provided the scopes in the application as an auth object (which you have already done):
const auth = new GoogleAuth({
scopes: ['https://www.googleapis.com/auth/calendar',
'https://www.googleapis.com/auth/compute']
});
- Enabled the Calendar API in the GCP console for your Service Account GCP Project.
- Provided the required scopes for your service account in the OAuth consent screen settings in GCP.
- Added the required scopes to the service account in the Google Admin console. This is done by following the
Security > Advanced Settings > Manage API client access
UI elements, and assigning all scopes the service account needs to the service account client ID.
Note: This final step must be done by a domain admin and can not be done by anyone who is not.
In this case, you will need to contact your domain admin to give your project API access.
References:
- Google API Console
- Google Admin Console
Related Answers:
- Google Calendar API. Adding an event to someone calendar throws error “Error 401: invalid_client” just when authenticating
GET/ADD Events to google calendar with a service account
Service account is a dummy user. It has its own Google Calendar account. By default it doesn't have access to any Google Calendars you need to either share a google calendar with it or insert a new Google Calendars into it.
Calendar.list is something else entirely its basically the little box at the bottom left in the Calendars website. In order for a calendar to appear there it I needs to be inserted into the calendar.list.
Solution:
Go to the Google calendar website add the service account email address as a user of your calendar. Then the service account will be able to access it. If you want you can programmatically insert it into calendar.list if you really need it to be there. IMO there is really not much point for Calendar.list with a service account.
update
You should be able to grant your service account access to do what ever you like like any other user.
If you want it in calendar.list call Calendarlist.insert from the service account code. You will only need to run it once to insert the calendar in question into the service accounts calendar list.
try running Calendars.get on the calendar it should have access without needing to insert it into calendar.list
Insert event in google calendar using service account with Nodejs
This is a known bug
There is an issue when adding attendees to an event with a Service Account.
The current workaround is to impersonate a user using G Suite Domain-wide Delegation. If you do so, you should be able to create the events with attendees.
Another option is to remove the attendees from the Event creation request.
Google service account unable to list calendars?
From your explanation and the returned value, I'm worried that in your situation, you might have never inserted the shared Calendar with the service account. If my understanding is correct, how about the following modification?
Modification points:
Insert the shared Calendar to the service account.
In this case, please modify the scope
https://www.googleapis.com/auth/calendar.readonly
tohttps://www.googleapis.com/auth/calendar
.async init () {
// loads the configuration from our app's configuration file
this.keyConfig = getKeyConfig('google-calendar');
const calendarApi = await this.getCalendarApi();
const response = await calendarApi.calendarList.insert({resource: {id: "###@group.calendar.google.com"}}); // Please set the Calendar ID here. Or {requestBody: {id: "###@group.calendar.google.com"}}
console.log(JSON.stringify(response.data, undefined, 2));
}
Retrieve the calendar list using your script.
- After the Calendar was inserted to the service account using the above script, you can obtain the shared Calendar in the Calendar list.
Reference:
- CalendarList: insert
What role and conditions are appropriate for allowing a service to add events to my google calendar?
https://support.google.com/a/answer/7378726?hl=en
Please follow the guide mentioned in above link to setup your service account. You can skip step 3 because you need service account instead of implementing OAuth consent screen to authenticate the account.
You may need G-Suit account if you get any trouble with setting up service account with your public gmail account.
You also need to enable Google calendar apis from library while setting up service account using above link. Otherwise you won't be able to access calendar apis.
After you setup up account accordingly, you need to follow the quick start guide according to your development platform. First you need to implement auth method where you will pass your service account keys to authenticate the account. And then you can call calendar apis using those auth credentials. You also need to define the scope in the auth method
Here are the available scopes of calendar apis
https://developers.google.com/calendar/api/guides/auth
In this link, there are some quick starts available in the left menu. You can pick one according to your need and start implementing it in your app.
Using a service account to create google calendar event, can't change creator name
I had a similar issue a long time ago, and the creator.displayName
documentation only stated that it would show if available, which was confusing.
After that, I found this Google issue tracker, which mentioned that the "if available" was referring to the Google+ profile information. I updated the name inside Google+, and it worked. Since Google+ is no longer available, I will say to try using Currents (which replaced Google+), and it should do the same thing.
You can access Currents here.
Reference:
- Issue tracker
- Evets overview
Cannot create events in google calendar with service account
You appear to have forgotten to specify which user you want the service account to delegate to.
from google.oauth2 import service_account
SCOPES = ['https://www.googleapis.com/auth/calendar']
SERVICE_ACCOUNT_FILE = '/path/to/service.json'
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
delegated_credentials = credentials.with_subject('user@example.org')
Related Topics
Update Query with Pdo and MySQL
PHP Multipart Form Data Put Request
How to Use PHP Array with SQL in Operator
Multiple Index Variables in PHP Foreach Loop
How to Encrypt PHP Source or Compile It So Others Can't See It? and How
How to Re-Format Datetime String in PHP
Find Number Which Is Greater Than or Equal to N in an Array
Getting Pear to Work on Xampp (Apache/MySQL Stack on Windows)
PHP Debug_Backtrace in Production Code to Get Information About Calling Method
How to Use "Root" Namespace of PHP
How to Get the Newest File in a Directory in PHP
How to Parse JSON into a HTML Table Using PHP
PHP Return 500 Error But No Error Log
Facebook Connect- $User_Id = $Facebook->Getuser(); Always Returning 0