google-apps-scriptoauth-2.0permissionsgoogle-calendar-api

Google Calendar Permissions for a Apps Script Accessing a Public Calendar


I'm trying to write a Google Apps Script that checks if certain days are holidays by accessing public holiday Google calendars.

I assumed this would only require the https://www.googleapis.com/auth/calendar.events.public.readonly permission, as mentioned in Google Calendar API scopes documentation.

However, I'm getting an exception attempting to run the following test code:

const HOLIDAY_CALENDAR_ID = "en.christian#holiday@group.v.calendar.google.com";

function checkHoliday() {
  const today = new Date();

  let holidayCalendar;
  try {
    holidayCalendar = CalendarApp.getCalendarById(HOLIDAY_CALENDAR_ID);
    if (!holidayCalendar) {
      Logger.log(`ERROR: Holiday calendar not found with ID: ${HOLIDAY_CALENDAR_ID}. Please check the ID.`);
      return; // Stop execution if calendar is not found
    }
  } catch (e) {
    Logger.log(`ERROR accessing holiday calendar: ${e.toString()}`);
    return;
  }
}

With the following appsscript.json:

{
  "timeZone": "America/New_York",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "oauthScopes": [
    "https://www.googleapis.com/auth/calendar.events.public.readonly",
    "https://www.googleapis.com/auth/gmail.send",
    "https://www.googleapis.com/auth/script.scriptapp",
    "https://www.googleapis.com/auth/script.container.ui"
  ]
}

Exception:

Specified permissions are not sufficient to perform the action. Required permissions: (https://www.googleapis.com/auth/calendar || https://www.googleapis.com/auth/calendar.readonly || https://www.google.com/calendar/feeds)

The permissions mentioned in the exception provide full access for all of the user's private calendars, which is inappropriate. How can I modify the script it so that the https://www.googleapis.com/auth/calendar.events.public.readonly permission will suffice, for the sole purpose of reading events in a public holiday calendar?


Solution

  • I think that the scopes https://www.googleapis.com/auth/calendar || https://www.googleapis.com/auth/calendar.readonly || https://www.google.com/calendar/feeds are required to use CalendarApp.getCalendarById of Calendar Service. Ref In your situation, the Calendar API might be suitable. Ref When this is reflected in your script, how about the following modification?

    Modified script:

    Before you test this script, please enable Calendar API at Advanced Google services. Ref

    In this case, this script works by only the scope of https://www.googleapis.com/auth/calendar.events.public.readonly.

    const HOLIDAY_CALENDAR_ID = "en.christian#holiday@group.v.calendar.google.com";
    
    function checkHoliday() {
      const today = new Date();
    
      let holidayCalendar;
      try {
    
        holidayCalendar = Calendar.Events.list(HOLIDAY_CALENDAR_ID);
    
        // Confirm the event list as a test.
        const events = holidayCalendar.items.map(({ summary }) => summary);
        console.log(events);
    
        if (!holidayCalendar) {
          Logger.log(`ERROR: Holiday calendar not found with ID: ${HOLIDAY_CALENDAR_ID}. Please check the ID.`);
          return; // Stop execution if calendar is not found
        }
      } catch (e) {
        Logger.log(`ERROR accessing holiday calendar: ${e.toString()}`);
        return;
      }
    }
    

    Testing:

    When this script is run, the following result is obtained.

    [ 
      'Epiphany',
      'Shrove Tuesday/Mardi Gras',
      'Maundy Thursday',
      'Good Friday',
      'Easter Monday',
      'All Saints\' Day',
      'Christmas Day (substitute)',
      'Epiphany',
      'Palm Sunday',
      'Corpus Christi',
      'Epiphany',
      'St. David\'s Day',
      'Palm Sunday',
      'Maundy Thursday',
      ,
      ,
      ,
    ]
    

    References: