Google Calendar integration with NodeJS without OAuth 2.0
Tags: google, calendar, node, javascript
Published: 2020-06-01 03:11:11

---
title: Google Calendar integration with NodeJS without OAuth 2.0
published: true
description: This post is to give a little more insight of how to use Google calendar inside NodeJS, I was struggling to implement this because of lack of documentation.
tags: google, calendar, nodejs, javascript
//cover_image: 
---

# Google Calendar integration
## Prerequisites
- This was done using a G-Suite account, I'm not sure this can be done with a normal Gmail account.
- a Google cloud project
- NodeJS and NPM/Yarn installed
- Basic knowledge of JavaScript and ES6

## Introduction
A client asked me to integrate a scheduling system into her website, to facilitate her appointments. I told her it would be an expensive solution written by hand as she is only a small company. However I'm always up to learn new stuff and looked into ways to make it happen. One of the first things I thought about and is part our daily lives is Google Calendar. It's easy and robust. So I took a look at the APIs and what and/or if it was possible to integrate it.

#### Headaches and solutions (this part can be skipped)
With the NPM package `googleapis` you have access to various Google services. However in my opinion the APIs are documented in a strange way, various parts in one place other parts in another, I wasn't always sure if parts were really related to the NPM package.

It took me a long time to understand authentication part. After trying the APIs with OAuth 2.0 my application was working. But the token was short lived. I didn't want the headache of repeating the authentication process. I thought that there should be some other way so I looked into API keys. Google provides this but not for every API, but calendar wasn't supported. The solution finally came after lots of searching and reading. A Google service account. That's what I'm going to share with you guys today. It's actually pretty darn easy.

## Setting up a Google Service Account (in the Google Cloud Console)
Obs. This article will not go in to depth setting up a Google Cloud Project

In the console go to `IAM And Management -> Service accounts` and create a new service account. Give it a name, an ID (this is also an email we'll need later on) and a description. Click Create. This account doesn't need permissions. Click Continue. This account doesn't need a service account user nor admin. But we'll need a JSON key. A file will be downloaded that we'll need later on.

## The calendar
We'll now add the service account email (ID) to the calendar. Add it to the Calendar. Click [here](https://support.google.com/calendar/answer/37082?hl=en) to know how to. The email should have the following permission `Make changes to events`.

The calendar ID can be found [here](https://help.crystalcommerce.com/en/articles/1389811-how-to-find-your-google-calendar-id), we'll also need it.

Well that was easy wasn't it, not everything needs to be bureaucratic.

## The fun part
Now we'll run some basic NodeJS tests, make new project dir with `npm init -y` and install `npm i -s googleapis date-fns` to the project. Date-fns we'll use to format and manipulate dates. Copy the credentials json file in to the root of the project directory.

Let's create an get.js with the following code:
```javascript
const { addWeeks } = require('date-fns')
const { google } = require('googleapis')
const credentials = require('<CREDENTIALS_FILE>.json')

const scopes = ['https://www.googleapis.com/auth/calendar']

const client = google.auth.getClient({
  credentials,
  scopes,
})

client.subject = '<SERVICE_ACCOUNT_EMAIL>'

const calendar = google.calendar({ version: 'v3', auth: client })

calendar.events.list(
  {
    calendarId: '<CALENDAR_ID>',
    timeMin: new Date().toISOString(),
    timeMax: addWeeks(new Date(), 1).toISOString(), // Let's get events for one week
    singleEvents: true,
    orderBy: 'startTime',
  },
  (err, res) => {
    if (err) {
      console.log(`The API returned an error: ${err}`)
    }
    // console.log(res.data.items) // All data
    const appointments = res.data.items.map((appointment) => ({
      start: appointment.start.dateTime || appointment.start.date,
      end: appointment.end.dateTime || appointment.end.date,
      id: appointment.id,
      status: appointment.status,
      creator: appointment.creator,
      description: appointment.description,
    }))
    console.log(appointments)
  },
)

```

and let's also create a new calendar event:
```javascript
const { addMinutes } = require('date-fns')
const { google } = require('googleapis')
const credentials = require('<CREDENTIALS_FILE>.json')

const scopes = ['https://www.googleapis.com/auth/calendar']

const client = google.auth.getClient({
  credentials,
  scopes,
})

client.subject = '<SERVICE_ACCOUNT_EMAIL>'

const calendar = google.calendar({ version: 'v3', auth: client })

calendar.events.insert(
  {
    calendarId: '<CALENDAR_ID>',
    resource: {
      start: {
        dateTime: new Date().toISOString(),
        timeZone: '<TIMEZONE>',
      },
      end: {
        dateTime: addMinutes(new Date(), 60).toISOString(),
        timeZone: '<TIMEZONE>',
      },
      summary: 'Test event',
      status: 'confirmed',
      description: 'Test description',
    },
  },
  (err, event) => {
    if (err) console.log('Error', err)
    console.log(event.data)
  },
)
```

This was a lot of work to find and figure out. I learned a lot, especially that it actually wasn't that hard!

This is my first post, help me with my writing skills and share your thoughts!

Hope it's of good use, happy hacking!