Integrating Google Calendar API to web app using serverless Node.js functions (Part 2 of 2)

Karan Bhomia
5 min readOct 12, 2018

--

In this part of the series, we would look at actual Node.js code for Authorization and fetching data from Google Calendar API. We would also deploy this code to a serverless compute platform, Google Cloud Functions.

Prerequisites

You have read the part 1 of this series. Also, you have the “Credentials.json” file which was downloaded as the last step of the previous article.

The user interaction with the web app

The workflow would be something like this :

Developing the Google Cloud Functions

We would be developing and deploying 2 functions

  1. authorize
    This is the function that would be called when the authorization process is initiated by the user. It could be triggered by click of a button on the UI.
    For this article, we would just directly invoke the function via Google Cloud Functions URL, which would look like
    `https://us-central1-<your project id>.cloudfunctions.net/authorize`
  2. token
    This is the function that would be called when the user actually clicks “Allow” on the consent screen.
    This would be hosted at `https://us-central1-<your project id>.cloudfunctions.net/token`

Let us begin

Go to terminal, navigate to your <project folder>/functions

Download and save googleapis npm module

npm i googleapis --save

Open <project_folder>/functions/index.js in your favorite IDE.
This file is supposed to export all the functions that you want to deploy on Google Cloud Functions.

Add the following code to it. We would soon go through this code line by line.

First of all we did a “require” on the modules needed.

const functions = require(‘firebase-functions’);
const {google} = require(‘googleapis’);

We exported a dummy “helloworld” function which just returns a string response.

We write a getCredentials function, which is supposed to return the JSON object that was present in credentials.json.
It is perfectly safe to include this in your codebase.

function getCredentials() {
return {}
//Replace this empty object with credentials.json contents
// Also, make sure your redirect_uris
}

The authorize function

exports.authorize = functions.https.onRequest((request, response) => {
console.log(‘Authorize called’)
const {client_secret, client_id, redirect_uris} = getCredentials().web
if(!client_secret || !client_id || !redirect_uris)
response.send(“Credentials missing”).status(500)
const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0])
let url = oAuth2Client.generateAuthUrl({
access_type: ‘offline’,
scope: SCOPES,
})
response.send(url)
})

The code here calls getCredentials function to read the parameters it needs to create the oAuth2Client.
It then uses the oAuth2Client to generate the authorization URL.

Notice that we have set a configuration parameter “access_type” as ‘offline’. This would let us fetch data from the Google Calendar API even when the user is not online.

So, we have developed our authorize function which returns a URL to the consent screen.

The token function

exports.token = functions.https.onRequest((request, response) => {
console.log(‘token called ‘ + JSON.stringify(request.body))
const code = request && request.query && request.query.code || null
if(!code)
response.send(“code missing”).status(400)
const {client_secret, client_id, redirect_uris} = getCredentials().web if(!client_secret || !client_id || !redirect_uris)
response.send(“Credentials missing”).status(500)
const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0])
oAuth2Client.getToken(code, (err, token) => {
if(err) {
console.log(‘err ‘ + err.message)
response.status(500).send(“Unable to generate token “ + err.message)
}
oAuth2Client.setCredentials(token)
fetchEvents(oAuth2Client)
response.send(“Access Granted. Please close this tab and continue.”)
})
})

First of all, we read a “code” from the query parameters of the request. This code is provided by the Google API when the /token function is invoked.

The logic here reads credentials from getCredentials function, creates the oAuth2Client.

Then, this oAuth2Client is used to fetch the actual token information by providing the code as a parameter to the async function getToken.

Once the token is returned, the callback function sets the token as credentials to the oAuth2Client.

This oAuth2Client is then used to fetch events from the Google Calendar API as you can see in the fetchEvents function.

function fetchEvents(auth) {
const calendar = google.calendar({version: 'v3', auth})
calendar.events.list({
calendarId: 'primary',
timeMin: (new Date()).toISOString(),
maxResults: 10,
singleEvents: true,
orderBy: 'startTime',
}, (err, res) => {
if (err) return console.log('The API returned an error: ' + err);
const events = res.data.items;
if (events.length) {
console.log('Upcoming 10 events:');
events.map((event, i) => {
const start = event.start.dateTime || event.start.date;
console.log(`${start} - ${event.summary}`);
});
} else {
console.log('No upcoming events found.');
}
})
}

Deploying your functions

Run the following command

firebase deploy --only functions

That’s it.

You can check the deployed functions and their health at the Firebase console.
Also, please notice the URLs shown under the “Trigger” column.

Testing

Open the authorize trigger URL in your browser. It would be in the following format.

https://us-central1-<your-project-id>.cloudfunctions.net/authorize

This function would return the URL for the consent screen.

Open the returned URL in the same tab. Here’s our consent screen. :)

Click “Allow”. It would result in the following screen.

So, the flow ran as expected. But how do I check the logs for the event details I console logged?

Go to Firebase Console . Navigate to “Functions”>”Logs

What can I do from here?

  1. Use these Google Cloud Functions with your Angular app. Maybe add a nice UI for the user to click “Connect Google Calendar” button and then have your services call the cloud functions URL.
  2. Store the token data in database and use it to pull data regularly. Please see Google Cloud Firestore.
  3. Use this code as a gateway to Google Calendar APIs. Please explore them here.

I would like to mention that I have missed out on a lot of details, for the sake of keeping this article short and concise. I leave it up to the reader’s interest to dig deep on anything that you may find interesting.

Written with ❤

--

--